#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
类型推断系统

实现自动类型推导、约束生成和求解功能。
支持局部类型推断、全局类型推断和增量类型推断。
"""

from copy import deepcopy, copy
from dataclasses import dataclass, field
from typing import TYPE_CHECKING, List, Optional, cast
from enum import Enum, auto

from mcpy.ir import IRStmtBlock
from mcpy.ir.base import IRNode, Parameter
from mcpy.ir.expressions.access import IRSubscript, IRSlice
from mcpy.ir.expressions.basic import IRName
from mcpy.ir.expressions.comprehension import (
    IRListComp,
    IRSetComp,
    IRDictComp,
    IRGeneratorExp,
    IRComprehension,
)
from mcpy.ir.statements.control import IRForRange, IRForEach
from .symbol_meta import (
    TypeInfo,
    TypeKind,
    SymbolKind,
)
from .type_system import parse_type
from .ir.expressions import (
    IRExpr,
    IRConstant,
    IRName,
    IRCall,
    IRAttribute,
    IRCompare,
    IRBoolOp,
    IRDict,
    IRList,
    IRSet,
    IRTuple,
    IRBinOp,
    IRUnaryOp,
)
from .ir.expressions.lambda_expr import IRLambda
from .ir.declarations import (
    IRFunctionNode,
    IRClassNode,
    IRMethodNode,
    IRPropertyNode,
    IREnumNode,
    IRImportNode,
)
from .ir.statements import IRExceptionHandler, IRReturn, IRAssign, IRTryExcept, IRIf
from .ir.statements.control import IRBreak, IRContinue
from .ir.statements.exception import IRRaise
from .ir.expressions.await_expr import IRAwait
from .symbol_meta import Symbol, TypeKind
from mcpy.symbol_registry import get_global_registry
from mcpy.symbol_meta import build_type_signature
from .ir.declarations.import_node import ImportKind
from mcpy.type_system import parse_type_with_context
from mcpy.type_system import is_protocol_type
from .ir.declarations.typevar import IRTypeVar
from mcpy.type_system import (
    resolve_type_annotation,
    is_protocol_implementation,
    is_callable_compatible,
    types_compatible,
)
from mcpy.analysis.type_narrowing import TypeNarrowingInfo, WrapperTypeRegistry
from mcpy.codegen.errors import CodeGenError

if TYPE_CHECKING:
    from .compiler import MCPyCompiler

method_symbols = [
    SymbolKind.VARIABLE,
    SymbolKind.PARAMETER,
    SymbolKind.CLASS,
    SymbolKind.MODULE,
]


class InferenceMode(Enum):
    """推断模式"""

    LOCAL = auto()  # 局部推断（函数内）
    GLOBAL = auto()  # 全局推断（模块级）
    INCREMENTAL = auto()  # 增量推断（编辑时）
    STRICT = auto()  # 严格推断（要求所有类型明确）
    PERMISSIVE = auto()  # 宽松推断（允许Any类型）


@dataclass
class InferenceContext:
    """推断上下文"""

    mode: InferenceMode = InferenceMode.LOCAL
    error_messages: List[str] = field(default_factory=list)
    current_class_type: Optional[TypeInfo] = None  # 当前正在推断的类类型
    infer_stack: List[IRNode] = field(default_factory=list)

    # 类型收窄上下文（变量名 -> 收窄信息）
    # 在遍历 if 语句时，会将条件中的类型守卫信息注入到此上下文
    narrowed_types: dict = field(default_factory=dict)
    compiler: Optional["MCPyCompiler"] = None
    # 期望类型（用于类型提示，如 return 语句中的空列表）
    expected_type: Optional[TypeInfo] = None
    # 当前函数节点（用于获取返回类型）
    current_function: Optional["IRFunctionNode"] = None

    def add_error(self, message: str) -> None:
        """添加错误消息"""
        self.error_messages.append(message)

    def with_class_type(self, class_type: TypeInfo) -> "InferenceContext":
        """创建带有指定类类型的新上下文"""
        return InferenceContext(
            mode=self.mode,
            error_messages=self.error_messages,
            current_class_type=class_type,
            infer_stack=self.infer_stack,
            compiler=self.compiler,
            expected_type=self.expected_type,
            current_function=self.current_function,
            narrowed_types=self.narrowed_types,  # ✅ 传递类型收窄信息
        )

    def with_expected_type(
        self, expected_type: Optional[TypeInfo]
    ) -> "InferenceContext":
        """创建带有期望类型的新上下文

        注意：必须传递 narrowed_types，以确保类型收窄在所有上下文中生效
        """
        return InferenceContext(
            mode=self.mode,
            error_messages=self.error_messages,
            current_class_type=self.current_class_type,
            infer_stack=self.infer_stack,  # 共享infer_stack，不复制
            compiler=self.compiler,
            expected_type=expected_type,
            current_function=self.current_function,
            narrowed_types=self.narrowed_types,  # ✅ 传递类型收窄信息
        )

    def enter_node(self, node: IRNode) -> None:
        """进入新节点"""
        if node in self.infer_stack:
            raise ValueError(f"循环引用检测到：{node}")
        self.infer_stack.append(node)

    def exit_node(self) -> None:
        """退出节点"""
        self.infer_stack.pop()


class TypeInferenceEngine:
    """类型推断引擎"""

    def __init__(self):
        self._inference_handlers = self._build_inference_handlers()
        # 初始化 WrapperTypeRegistry（用于类型收窄）
        self._wrapper_registry = WrapperTypeRegistry()

    def _build_inference_handlers(self):
        """构建类型推断处理器映射表"""
        return {
            # === 表达式类型推断 ===
            # 基础表达式
            "constant": self._infer_constant_type,
            "name": self._infer_name_type,
            "call": self._infer_call_type,
            "attribute": self._infer_attribute_type,
            # 运算符表达式
            "bin_op": self._infer_binop_type,
            "unary_op": self._infer_unaryop_type,
            "compare": self._infer_compare_type,
            "bool_op": self._infer_boolop_type,
            # 字面量表达式
            "list": self._infer_list_type,
            "dict": self._infer_dict_type,
            "tuple": self._infer_tuple_type,
            "set": self._infer_set_type,
            # 访问表达式
            "subscript": self._infer_subscript_type,
            # 推导式表达式
            "list_comp": self._infer_list_comprehension_type,
            "set_comp": self._infer_set_comprehension_type,
            "dict_comp": self._infer_dict_comprehension_type,
            "generator_exp": self._infer_generator_comprehension_type,
            "comprehension": self._infer_comprehension_type,
            # 字符串格式化表达式
            "sformat": self._infer_sformat_type,
            # Lambda 表达式
            "lambda": self._infer_lambda_type,
            # Await 表达式
            "await": self._infer_await_type,
            # === 声明类型推断 ===
            "parameter": self._infer_parameter_type,
            "function": self.infer_function_type,
            "class": self._infer_class_type,
            "method": self._infer_method_type,
            "property": self._infer_property_type,
            "enum": self._infer_enum_type,
            "import": self._infer_import_type,
            "typevar": self._infer_typevar_type,
            # === 语句类型推断 ===
            "assign": self.infer_assignment_type,
            "augassign": self._infer_aug_assign_type,
            "return": self._infer_return_type,
            "expr_stmt": self._infer_expr_stmt_type,
            "stmt_block": self._infer_stmt_block_type,
            "if": self._infer_control_flow_type,
            "for_range": self._infer_for_range_type,
            "for_each": self._infer_for_each_type,
            "while": self._infer_control_flow_type,
            "conditional": self._infer_conditional_type,
            # 异常处理
            "try_except": self._infer_try_except_type,
            "exception_handler": self._infer_exception_handler_type,
            "raise": self._infer_raise_type,
        }

    def _infer_base_class_type(
        self, base_name: str, node: IRClassNode, context: InferenceContext
    ) -> TypeInfo:
        base_symbol = node.lookup_symbol(base_name)
        assert base_symbol, f"基类 {base_name} 未定义"
        assert base_symbol.kind == SymbolKind.CLASS, f"基类 {base_name} 不是类类型"
        if base_symbol.type_info:
            return base_symbol.type_info
        assert (
            base_symbol.ir_node
        ), f"推导类型失败：符号 {base_symbol.name} 未关联 IR 节点"
        type_info = self.infer_type(base_symbol.ir_node, context)
        base_symbol.set_type_info(type_info)
        return type_info

    def _infer_class_type(
        self, node: IRClassNode, context: InferenceContext
    ) -> TypeInfo:
        """类声明类型推断

        Args:
            node: 类节点
            context: 推断上下文

        Returns:
            类的类型信息
        """
        if not node.name:
            return TypeInfo.unknown()

        # 创建类类型信息
        class_type = TypeInfo(
            kind=TypeKind.CLASS, name=node.name, module=getattr(node, "module", None)
        )

        # 处理基类
        for base_name in node.bases:
            base_type = self._infer_base_class_type(base_name, node, context)
            class_type.base_types.append(base_type)

        class_context = context.with_class_type(class_type)

        # 第一阶段：先注册所有方法符号到class_type，这样方法之间可以互相引用
        for symbol in node.walk_local_symbols():
            if (
                symbol.kind == SymbolKind.METHOD
                and symbol.name not in class_type.methods
            ):
                class_type.methods[symbol.name] = symbol
            elif (
                symbol.kind == SymbolKind.ATTRIBUTE
                and symbol.name not in class_type.attributes
            ):
                class_type.attributes[symbol.name] = symbol

        # 第二阶段：推导所有成员的类型
        for symbol in node.walk_local_symbols():
            assert symbol.ir_node, f"推导类型失败：符号 {symbol.name} 未关联 IR 节点"
            if not symbol.type_info:
                symbol_type = self.infer_type(symbol.ir_node, class_context)
                symbol.set_type_info(symbol_type)

        return class_type

    def _infer_return_type_from_function(
        self, node: IRFunctionNode | IRMethodNode, context
    ):
        """从函数或方法节点推断返回类型

        Args:
            node: 函数或方法节点 (IRFunctionNode 或 IRMethodNode)
            context: 推断上下文

        Returns:
            推断出的返回类型
        """
        # 解析显式的返回类型注解（如果有）
        annotated_return_type = None
        if node.return_type:
            annotated_return_type = parse_type(node.return_type, node)

            # 如果注解是具体类型（非协议），直接返回，不推导 return 语句
            # 这避免了循环引用问题，也提高了性能
            if annotated_return_type and not is_protocol_type(
                annotated_return_type, node
            ):
                return annotated_return_type

        # 只有在以下情况才推导 return 语句：
        # 1. 没有返回类型注解
        # 2. 返回类型注解是协议（需要推导实际类型）

        # 创建带有当前函数的上下文
        func_context = InferenceContext(
            mode=context.mode,
            error_messages=context.error_messages,
            current_class_type=context.current_class_type,
            infer_stack=context.infer_stack.copy(),
            compiler=context.compiler,
            expected_type=annotated_return_type,  # 将注解作为期望类型传递
            current_function=node,
        )

        # 第一遍：推导函数体中的所有语句，建立局部变量类型信息
        # 这样在推导 return 语句时，所有引用的变量都已经有类型信息，避免递归
        # 第一遍遍历时，只捕获未定义符号相关的错误，其他错误正常传播
        for stmt in node.body.statements:
            if not isinstance(stmt, IRReturn):
                try:
                    self.infer_type(stmt, func_context)
                except AssertionError as e:
                    # 只捕获未定义相关的错误，其他错误应该传播
                    error_msg = str(e)
                    if "未定义" in error_msg or "不存在" in error_msg:
                        # 第一遍遍历时忽略未定义错误，继续处理其他语句
                        pass
                    else:
                        # 其他assertion错误应该重新抛出
                        raise
                except Exception:
                    # 其他类型的异常也忽略（如类型转换错误等）
                    pass

        # 第二遍：从函数体中的return语句推导返回类型
        return_types = []
        for stmt in node.body.statements:
            if isinstance(stmt, IRReturn):
                return_types.append(self.infer_type(stmt, func_context))

        # 确定推导的返回类型
        if len(return_types) == 0:
            inferred_return_type = TypeInfo.none()
        elif len(return_types) == 1:
            inferred_return_type = return_types[0]
        else:
            # 合并多个返回类型
            inferred_return_type = TypeInfo(
                kind=TypeKind.TUPLE,
                name="Tuple",
                args=return_types,
            )

        # async函数：将返回类型包装成Coroutine[Any, Any, T]
        if hasattr(node, "is_async") and node.is_async:
            # Coroutine[YieldType, SendType, ReturnType]
            # Python中async函数返回Coroutine[Any, Any, T]
            any_type = TypeInfo(kind=TypeKind.ANY, name="Any")
            inferred_return_type = TypeInfo(
                kind=TypeKind.GENERIC,
                name="Coroutine",
                args=[any_type, any_type, inferred_return_type],
                return_type=inferred_return_type,  # 第三个参数是实际的返回类型
            )

        # 协议注解：使用推导的实际类型
        return inferred_return_type

    def _infer_parameter_type(self, node: Parameter, context):
        """参数声明类型推断"""
        type_info = self._get_cached_type(node)
        if type_info:
            return type_info

        if node.type_annotation:
            return parse_type(node.type_annotation, node)
        elif isinstance(node.parent, IRMethodNode) and node.name == "self":
            return context.current_class_type
        return TypeInfo.any()

    def _infer_parameter_types(self, node: IRFunctionNode | IRMethodNode, context):
        """推断函数或方法的参数类型

        Args:
            node: 函数或方法节点 (IRFunctionNode 或 IRMethodNode)
            context: 推断上下文

        Returns:
            参数类型列表
        """
        param_types = []
        for param in node.walk_local_symbols(kind=SymbolKind.PARAMETER):
            assert param.ir_node, f"推导类型失败：参数 {param.name} 未关联 IR 节点"
            if not param.type_info:
                type_info = self.infer_type(param.ir_node, context)
                param.set_type_info(type_info)
            param_types.append(param.type_info)

        return param_types

    def _infer_method_type(self, node: IRMethodNode, context):
        """方法声明类型推断"""

        # 推断返回类型
        return_type = self._infer_return_type_from_function(node, context)

        # 推断参数类型
        param_types = self._infer_parameter_types(node, context)

        # 创建函数类型信息
        method_type = TypeInfo(
            kind=TypeKind.FUNCTION,
            name=node.name,
            args=param_types,
            return_type=return_type,
        )

        return method_type

    def _infer_enum_type(self, node: IREnumNode, context):
        """枚举声明类型推断"""

        # 创建枚举类型
        enum_type = TypeInfo(
            kind=TypeKind.CLASS,  # 枚举在C++中通常作为类处理
            name=node.name or "enum",
        )

        # 处理枚举成员
        for member_symbol in node.walk_local_symbols():
            enum_type.attributes[member_symbol.name] = member_symbol

        return enum_type

    def _infer_import_type(self, node: IRImportNode, context):
        """导入声明类型推断"""

        node.resolve_import(context.compiler)
        if node.name == "int32_t":
            node.name = "int32_t"

        module_path = (
            node.source_module
            if node.import_kind == ImportKind.FROM_IMPORT
            else ",".join(node.imported_modules)
        )
        module_type = TypeInfo(
            kind=TypeKind.MODULE,
            name=node.name,
            module=module_path,
        )

        return module_type

    def _infer_typevar_type(self, node, context):
        """TypeVar 声明类型推断"""
        if isinstance(node, IRTypeVar):
            # 直接返回 TypeVar 节点的类型信息
            return node.get_type_info()

        # 如果不是 IRTypeVar 节点，返回未知类型
        return TypeInfo.unknown()

    def _infer_aug_assign_type(self, node, context):
        """增强赋值语句类型推断

        增强赋值（如 `a += b`）会调用相应的特殊方法（如 `__iadd__`）。
        我们需要：
        1. 获取左侧变量的类型
        2. 查找对应的增强赋值方法
        3. 获取方法的参数类型
        4. 将参数类型作为期望类型传递给右侧表达式
        """
        # 获取左侧变量的类型
        target_symbol = node.lookup_symbol(node.target)
        if not target_symbol:
            # 如果找不到符号，直接推导右侧表达式（无期望类型）
            if node.value:
                self.infer_type(node.value, context)
            return TypeInfo.none()

        target_type = target_symbol.get_type_info(context)
        if not target_type:
            # 如果找不到类型，直接推导右侧表达式（无期望类型）
            if node.value:
                self.infer_type(node.value, context)
            return TypeInfo.none()

        # 映射操作符到特殊方法名
        op_to_method = {
            "+": "__iadd__",
            "-": "__isub__",
            "*": "__imul__",
            "/": "__itruediv__",
            "//": "__ifloordiv__",
            "%": "__imod__",
            "**": "__ipow__",
            "<<": "__ilshift__",
            ">>": "__irshift__",
            "&": "__iand__",
            "^": "__ixor__",
            "|": "__ior__",
        }

        method_name = op_to_method.get(node.op)
        if not method_name:
            # 如果找不到对应的方法，直接推导右侧表达式（无期望类型）
            if node.value:
                self.infer_type(node.value, context)
            return TypeInfo.none()

        # 查找增强赋值方法
        registry = get_global_registry()
        type_str = build_type_signature(target_type)
        method_symbol = registry.lookup_instance_method(
            type_str,  # 完整类型签名，如 "list[int]"
            method_name,  # 方法名，如 "__iadd__"
            [],  # 参数类型列表（为空，因为我们还没推导）
        )

        if method_symbol and method_symbol.type_info and method_symbol.type_info.args:
            # 方法的第一个参数是 self，第二个参数才是我们需要的
            if len(method_symbol.type_info.args) > 1:
                param_type = method_symbol.type_info.args[1]
                # 使用参数类型作为期望类型推导右侧表达式
                value_context = context.with_expected_type(param_type)
                if node.value:
                    self.infer_type(node.value, value_context)
                return target_type  # 增强赋值返回左侧类型

        # 如果没有找到方法或方法没有参数类型，直接推导右侧表达式（无期望类型）
        if node.value:
            self.infer_type(node.value, context)
        return TypeInfo.none()

    def _infer_return_type(self, node, context):
        """Return语句类型推断"""
        if hasattr(node, "expr") and node.expr:
            # 获取函数返回类型作为提示
            expected_return_type = None
            if context.current_function:
                if context.current_function.return_type:
                    expected_return_type = parse_type(
                        context.current_function.return_type, context.current_function
                    )

            # 使用期望类型推断表达式
            if expected_return_type:
                context_with_hint = context.with_expected_type(expected_return_type)
                return self.infer_type(node.expr, context_with_hint)
            else:
                return self.infer_type(node.expr, context)
        else:
            return TypeInfo.none()

    def _infer_expr_stmt_type(self, node, context):
        """表达式语句类型推断"""
        return self.infer_type(node.expr, context)

    def _infer_stmt_block_type(self, node, context):
        """语句块类型推断"""
        # 动态导入避免循环导入

        return TypeInfo.none()

    def _infer_control_flow_type(self, node, context):
        """控制流语句类型推断

        对于 if 语句，会分析类型守卫并在相应分支中应用类型收窄。
        对于其他控制流语句，返回 None。
        """
        # 如果是 if 语句，进行类型守卫分析
        if isinstance(node, IRIf):
            return self._infer_if_with_type_narrowing(node, context)

        # 其他控制流语句返回 None
        return TypeInfo.none()

    def _infer_if_with_type_narrowing(
        self, if_node: IRIf, context: InferenceContext
    ) -> TypeInfo:
        """推导 if 语句类型并应用类型收窄

        支持：
        1. 正向类型守卫：在 then_body 中应用收窄
        2. 负向类型守卫：如果 then_body 一定终止，在 if 语句之后应用反向收窄

        Args:
            if_node: if 语句节点
            context: 推断上下文

        Returns:
            类型信息（if 语句本身不返回值，返回 None）
        """
        # 1. 先推导条件表达式的类型
        self.infer_type(if_node.test, context)

        # 2. 分析条件中的类型守卫
        narrowing_infos = self._analyze_type_guard(if_node.test, context)

        # 3. 在 then_body 中应用类型收窄（正向守卫）
        # 但要排除否定模式（negated_optional_check）
        if if_node.then_body:
            # 过滤出非否定的类型守卫
            positive_narrowing = {
                var_name: info
                for var_name, info in narrowing_infos.items()
                if info.narrowing_kind != "negated_optional_check"
            }

            if positive_narrowing:
                # 创建新的上下文，包含收窄信息
                if_context = InferenceContext(
                    mode=context.mode,
                    error_messages=context.error_messages,
                    current_class_type=context.current_class_type,
                    infer_stack=context.infer_stack.copy(),
                    compiler=context.compiler,
                    expected_type=context.expected_type,
                    current_function=context.current_function,
                    narrowed_types={**context.narrowed_types, **positive_narrowing},
                )

                # 推导 then_body，使用收窄后的类型
                self.infer_type(if_node.then_body, if_context)
            else:
                # 没有正向类型守卫，正常推导
                self.infer_type(if_node.then_body, context)

        # 4. 推导 else_body（不应用类型收窄）
        if if_node.else_body:
            self.infer_type(if_node.else_body, context)

        # 5. 负向类型守卫：如果 then_body 一定终止（break/return/raise），
        #    则在 if 语句之后应用反向收窄
        if narrowing_infos and if_node.then_body:
            if self._statement_always_terminates(if_node.then_body):
                # then_body 一定终止，说明 if 之后的代码在 "条件为假" 的情况下执行
                # 应用反向类型守卫到上下文中
                inverted_narrowing = self._invert_type_guard(narrowing_infos, context)

                if inverted_narrowing:
                    # 核心修复：将收窄信息附加到 if 之后的所有兄弟语句及其子节点
                    self._propagate_narrowing_to_siblings(if_node, inverted_narrowing)

                    # 同时也更新上下文（对于在同一作用域内的后续语句）
                    context.narrowed_types.update(inverted_narrowing)

        # if 语句本身不返回值
        return TypeInfo.none()

    def _statement_always_terminates(self, stmt_block) -> bool:
        """检查语句块是否一定会终止（不会继续执行后续代码）

        终止条件：
        - return 语句
        - break 语句（在循环中）
        - continue 语句（在循环中）
        - raise 语句

        Args:
            stmt_block: 语句块节点

        Returns:
            True 如果语句块一定终止
        """
        if not stmt_block or not hasattr(stmt_block, "statements"):
            return False

        # 检查语句块中是否有终止语句
        for stmt in stmt_block.statements:
            if isinstance(stmt, (IRReturn, IRBreak, IRContinue, IRRaise)):
                return True

            # 递归检查嵌套的 if 语句
            if isinstance(stmt, IRIf):
                # 如果 if 的所有分支都终止，则整个 if 语句终止
                then_terminates = (
                    self._statement_always_terminates(stmt.then_body)
                    if stmt.then_body
                    else False
                )
                else_terminates = (
                    self._statement_always_terminates(stmt.else_body)
                    if stmt.else_body
                    else False
                )

                # 只有当 then 和 else 都存在且都终止时，if 语句才一定终止
                if then_terminates and else_terminates and stmt.else_body:
                    return True

        return False

    def _propagate_narrowing_to_siblings(
        self, if_node: IRIf, narrowing_infos: dict[str, TypeNarrowingInfo]
    ) -> None:
        """将收窄信息传播到 if 之后的所有兄弟语句及其子节点

        Args:
            if_node: if 语句节点
            narrowing_infos: 类型收窄信息
        """
        # 找到 if 节点的父语句块
        parent = if_node.parent
        if not parent or not isinstance(parent, IRStmtBlock):
            return

        # 找到 if 节点在语句列表中的位置
        try:
            if_index = parent.statements.index(if_node)
        except (ValueError, AttributeError):
            return

        # 将收窄信息附加到 if 之后的所有语句及其子节点
        for i in range(if_index + 1, len(parent.statements)):
            sibling_stmt = parent.statements[i]

            # 附加到语句本身和所有子节点
            for var_name, narrowing_info in narrowing_infos.items():
                sibling_stmt.set_narrowing_info(var_name, narrowing_info)

                # 递归附加到所有子节点
                for child in sibling_stmt.walk():
                    child.set_narrowing_info(var_name, narrowing_info)

    def _invert_type_guard(
        self, narrowing_infos: dict[str, TypeNarrowingInfo], context: InferenceContext
    ) -> dict[str, TypeNarrowingInfo]:
        """反转类型守卫（用于负向守卫）

        例如：
        - if not num: break  →  在 if 之后，num 一定有值（收窄为 T）
        - if num is None: return  →  在 if 之后，num 一定不是 None（收窄为 T）
        - if num: break  →  在 if 之后，num 可能是 None（不收窄）

        Args:
            narrowing_infos: 原始类型守卫信息
            context: 推断上下文

        Returns:
            反转后的类型守卫信息
        """
        inverted = {}

        for var_name, info in narrowing_infos.items():
            # 否定模式：if not num: break
            # - then_body中：num 可能是 None（不收窄）
            # - then_body 终止后，if 之后：num 一定有值（收窄为 T）
            if info.narrowing_kind == "negated_optional_check":
                # 反转：应用收窄
                inverted[var_name] = TypeNarrowingInfo(
                    var_name=info.var_name,
                    original_type=info.original_type,
                    narrowed_type=info.narrowed_type,
                    narrowing_kind="optional_check",  # 反转为正向检查
                )

            # 正向模式：if num: break 或 if num is not None: return
            # - then_body中：num 一定有值（已收窄）
            # - then_body 终止后，if 之后：num 可能是 None（不应收窄）
            else:
                # 不应用反向收窄
                pass

        return inverted

    def _infer_conditional_type(self, node, context):
        """推断条件表达式（三元运算符）的类型

        对于 `a if condition else b`，类型应该是 a 和 b 的公共类型。
        简化实现：优先返回 body 的类型，如果无法推断则返回 orelse 的类型。

        Args:
            node: IRConditional 节点
            context: 推断上下文

        Returns:
            TypeInfo: 推断的类型
        """
        # 推断 body 和 orelse 的类型
        body_type = self.infer_type(node.body, context)
        orelse_type = self.infer_type(node.orelse, context)

        # 如果两个分支类型相同，直接返回
        if body_type and orelse_type and body_type.name == orelse_type.name:
            return body_type

        # 如果 body 有明确类型，优先使用 body 的类型
        if body_type and body_type.name != "Any":
            return body_type

        # 否则使用 orelse 的类型
        if orelse_type and orelse_type.name != "Any":
            return orelse_type

        # 如果都无法推断，返回 Any
        return TypeInfo.any()

    def _infer_try_except_type(self, node: IRTryExcept, context):
        """推断 try/except 语句类型

        try/except 作为语句不是表达式，不产生值，但需要推断其内部各个部分：
        1. try 块中的语句（可能包含 return 语句影响函数返回值）
        2. except 处理器（包括异常变量类型）
        3. else 块（可能包含 return 语句）
        4. finally 块

        Args:
            node: IRTryExcept 节点
            context: 推断上下文

        Returns:
            TypeInfo.none() - 语句本身的类型标记
        """
        # 推断 try 块
        if node.body:
            self.infer_type(node.body, context)

        # 推断 except 处理器（会推断异常变量类型）
        for handler in node.handlers:
            self.infer_type(handler, context)

        # 推断 else 块
        if node.orelse:
            self.infer_type(node.orelse, context)

        # 推断 finally 块
        if node.finalbody:
            self.infer_type(node.finalbody, context)

        return TypeInfo.none()

    def _infer_exception_handler_type(self, node: IRExceptionHandler, context):
        """推断异常处理器类型

        推断异常变量的类型并设置到符号表中

        Args:
            node: IRExceptionHandler 节点
            context: 推断上下文

        Returns:
            TypeInfo.none()
        """
        # 推断异常类型
        if node.type:
            exception_type = self.infer_type(node.type, context)

            # 如果有异常变量名，为其创建符号并设置类型
            if node.exception_name and exception_type:
                # 查找异常变量符号
                symbol = node.lookup_symbol(node.exception_name)
                if symbol:
                    symbol.set_type_info(exception_type)

        # 推断 handler body
        if node.body:
            self.infer_type(node.body, context)

        return TypeInfo.none()

    def _infer_raise_type(self, node, context):
        """推断 raise 语句类型

        Args:
            node: IRRaise 节点
            context: 推断上下文

        Returns:
            TypeInfo.none()
        """
        # 推断异常表达式类型
        if node.exc:
            self.infer_type(node.exc, context)

        # 推断 cause 表达式类型
        if node.cause:
            self.infer_type(node.cause, context)

        return TypeInfo.none()

    def _infer_for_range_type(self, node: IRForRange, context):
        """推断 for range 循环的类型，并设置循环变量类型"""
        # 推断 start, end, step 的类型
        start_type = self.infer_type(node.start, context)
        end_type = self.infer_type(node.end, context)
        step_type = self.infer_type(node.step, context)

        # 循环变量的类型基于 range 参数的类型
        # 通常 range 的参数都是 int，所以循环变量也是 int
        loop_var_type = TypeInfo(kind=TypeKind.PRIMITIVE, name="int")

        # 如果 start/end/step 有其他类型，使用更通用的类型
        if (
            (start_type and start_type.name == "float")
            or (end_type and end_type.name == "float")
            or (step_type and step_type.name == "float")
        ):
            loop_var_type = TypeInfo(kind=TypeKind.PRIMITIVE, name="float")

        # 为循环变量设置类型信息
        var_name = node.var.id
        symbol = node.lookup_symbol(var_name)
        if symbol:
            symbol.set_type_info(loop_var_type)
            node.set_extension_param(f"loop_var_{var_name}_type", loop_var_type)

        # IRForRange 节点本身返回 None（语句不需要返回值）
        return TypeInfo.none()

    def _infer_for_each_type(self, node: IRForEach, context):
        """推断 for each 循环的类型，并设置循环变量类型"""
        # 安全地推断迭代表达式的类型，避免循环引用
        iter_type = self.infer_type(node.iter_expr, context)

        # 检查是否是字典类型的迭代
        # Python 中 for key in dict 遍历的是键，需要转换为 for key in dict.keys()
        if self._is_dict_type(iter_type):
            # 创建 dict.keys() 调用
            # 1. 创建 IRAttribute 节点表示 dict.keys
            keys_attr = IRAttribute()
            keys_attr.value = node.iter_expr
            keys_attr.attr = "keys"
            keys_attr.parent = None  # 稍后设置

            # 2. 创建 IRCall 节点表示 dict.keys() 调用
            keys_call = IRCall()
            keys_call.func = keys_attr
            keys_call.args = []
            keys_call.keywords = []
            keys_call.parent = node

            # 3. 设置父节点关系
            keys_attr.parent = keys_call
            node.iter_expr.parent = keys_attr

            # 4. 替换迭代表达式
            node.iter_expr = keys_call

            # 5. 重新推导迭代表达式的类型
            iter_type = self.infer_type(node.iter_expr, context)

        # 根据迭代表达式的类型推断循环变量的类型，传入当前节点作为上下文
        loop_var_type = self._infer_loop_var_type_from_iterable(iter_type, node)

        # 为循环变量设置类型信息
        # 支持单变量和元组解包
        if isinstance(node.var, IRName):
            # 单变量：for x in ...
            var_name = node.var.id
            symbol = node.lookup_symbol(var_name)
            if symbol:
                symbol.set_type_info(loop_var_type)
                node.set_extension_param(f"loop_var_{var_name}_type", loop_var_type)
        else:
            # 元组解包：for x, y in ...
            # 为每个变量设置类型信息
            if hasattr(node.var, "elements"):
                elements = getattr(node.var, "elements")
                for i, element in enumerate(elements):
                    if isinstance(element, IRName):
                        var_name = element.id
                        symbol = node.lookup_symbol(var_name)
                        if symbol:
                            # 从元组类型中提取对应索引的元素类型
                            element_type = self._extract_tuple_element_type(
                                loop_var_type, i
                            )
                            symbol.set_type_info(element_type)
                            node.set_extension_param(
                                f"loop_var_{var_name}_type", element_type
                            )

        # IRForEach 节点本身返回 None（语句不需要返回值）
        return TypeInfo.none()

    def _extract_tuple_element_type(self, tuple_type: TypeInfo, index: int) -> TypeInfo:
        """从元组类型中提取指定索引的元素类型

        Args:
            tuple_type: 元组类型信息
            index: 元素索引

        Returns:
            元素类型信息，如果无法提取则返回 Any
        """
        # 如果是泛型元组类型（tuple[T1, T2, ...]）
        if (
            tuple_type.kind == TypeKind.GENERIC
            and tuple_type.name == "tuple"
            and tuple_type.args
        ):
            # 检查索引是否在范围内
            if 0 <= index < len(tuple_type.args):
                return tuple_type.args[index]

        # 如果无法提取，返回 Any 类型
        return TypeInfo.any()

    def _is_dict_type(self, type_info: Optional[TypeInfo]) -> bool:
        """判断类型是否是字典类型

        Args:
            type_info: 类型信息

        Returns:
            是否是字典类型
        """
        if not type_info:
            return False

        if type_info.name == "dict" or type_info.name == "Dict":
            return True

        return False

    def _infer_loop_var_type_from_iterable(
        self, iter_type: Optional[TypeInfo], context_node=None
    ) -> TypeInfo:
        """从可迭代对象的类型推断循环变量的类型"""
        if not iter_type:
            return TypeInfo(kind=TypeKind.ANY, name="Any")

        # 使用更通用的方法：基于 Python 迭代器协议
        return self._get_iterator_element_type(iter_type, context_node)

    def _get_iterator_element_type(
        self, iter_type: TypeInfo, context_node=None
    ) -> TypeInfo:
        """获取迭代器的元素类型，基于 Python 迭代器协议"""

        # 1. 优先：通过符号表查找 __iter__ 方法（支持第三方库和用户自定义类型）
        if context_node:
            iterator_type = self._get_iterator_type_from_symbol(iter_type, context_node)
            if iterator_type:
                return iterator_type

        # 2. 回退：处理泛型容器类型（内置类型的硬编码规则）
        if iter_type.kind == TypeKind.GENERIC and iter_type.args:
            return self._infer_generic_iterator_type(iter_type)

        # 3. 回退：处理基础类型的迭代（Python 内置类型的迭代行为）
        if iter_type.kind == TypeKind.PRIMITIVE:
            return self._infer_primitive_iterator_type(iter_type)

        # 4. 默认情况：返回 Any 类型
        return TypeInfo(kind=TypeKind.ANY, name="Any")

    def _infer_generic_iterator_type(self, iter_type: TypeInfo) -> TypeInfo:
        """推断泛型容器的迭代器类型"""
        type_name = iter_type.name

        # 容器类型 -> 迭代器元素类型的映射
        # 通过检查是否有类型参数来判断，而不是硬编码类型名称
        # 对于大多数泛型容器（list[T]、set[T]、dict[K,V]），迭代时返回第一个类型参数
        if iter_type.args and len(iter_type.args) > 0:
            # list[T] -> T, set[T] -> T
            # tuple[T1, T2, ...] -> T1 (简化为第一个类型)
            # dict[K, V] -> K (字典迭代默认迭代键)
            return iter_type.args[0]
        elif type_name.endswith("_iterator"):
            # 如果是迭代器类型本身，返回其元素类型
            return (
                iter_type.args[0]
                if iter_type.args
                else TypeInfo(kind=TypeKind.ANY, name="Any")
            )

        # 其他泛型类型，假设第一个类型参数是元素类型
        return iter_type.args[0]

    def _infer_primitive_iterator_type(self, iter_type: TypeInfo) -> TypeInfo:
        """推断基础类型的迭代器类型"""
        type_name = iter_type.name

        # Python 基础类型的迭代行为
        if type_name == "str":
            # 字符串迭代产生字符（在 Python 中仍是 str）
            return TypeInfo(kind=TypeKind.PRIMITIVE, name="str")
        elif type_name in ["bytes", "bytearray"]:
            # 字节类型迭代产生整数
            return TypeInfo(kind=TypeKind.PRIMITIVE, name="int")
        elif type_name == "range":
            # range 对象迭代产生整数
            return TypeInfo(kind=TypeKind.PRIMITIVE, name="int")

        # 其他基础类型不可迭代
        return TypeInfo(kind=TypeKind.ANY, name="Any")

    def _get_iterator_type_from_symbol(
        self, iter_type: TypeInfo, context_node
    ) -> Optional[TypeInfo]:
        """通过符号表查找迭代器类型信息"""
        try:
            # 1. 查找类型对应的符号
            type_symbol = context_node.lookup_symbol(iter_type.name)
            if not type_symbol:
                return None

            # 2. 查找 __iter__ 方法符号
            iter_method_name = f"{iter_type.name}.__iter__"
            iter_method_symbol = context_node.lookup_symbol(iter_method_name)

            if iter_method_symbol:
                # 3. 从 __iter__ 方法的类型信息获取返回类型
                return self._extract_iterator_element_type_from_method(
                    iter_method_symbol
                )

            # 4. 如果没有找到 __iter__ 方法，尝试查找类型的属性
            if type_symbol.type_info and hasattr(type_symbol.type_info, "methods"):
                iter_method = type_symbol.type_info.methods.get("__iter__")
                if iter_method:
                    return self._extract_iterator_element_type_from_method(iter_method)

        except Exception:
            # 如果查找过程中出现任何异常，返回 None
            pass

        return None

    def _extract_iterator_element_type_from_method(
        self, method_symbol
    ) -> Optional[TypeInfo]:
        """从 __iter__ 方法符号中提取迭代器元素类型"""
        try:
            # 获取方法的返回类型
            if hasattr(method_symbol, "type_info") and method_symbol.type_info:
                return_type = method_symbol.type_info.return_type
                if return_type:
                    # 如果返回类型是 Iterator[T] 或类似的泛型类型
                    if (
                        return_type.kind == TypeKind.GENERIC
                        and return_type.name in ["Iterator", "Iterable"]
                        and return_type.args
                    ):
                        return return_type.args[0]

                    # 如果返回类型本身就是元素类型（简化情况）
                    return return_type

            # 尝试从签名字符串解析（如果有的话）
            if hasattr(method_symbol, "signatures") and method_symbol.signatures:
                return self._parse_iterator_type_from_signature(
                    method_symbol.signatures[0]
                )

        except Exception:
            pass

        return None

    def _parse_iterator_type_from_signature(
        self, signature_str: str
    ) -> Optional[TypeInfo]:
        """从签名字符串解析迭代器元素类型"""
        try:
            # 解析类似 "__iter__(self) -> Iterator[T]" 的签名
            import re

            # 匹配返回类型部分
            match = re.search(r"->\s*([^,\)]+)", signature_str)
            if match:
                return_type_str = match.group(1).strip()

                # 解析泛型类型，如 Iterator[T], Iterable[int] 等
                generic_match = re.match(r"(\w+)\[(.+)\]", return_type_str)
                if generic_match:
                    container_type = generic_match.group(1)
                    element_type_str = generic_match.group(2).strip()

                    # 如果是已知的迭代器类型，返回元素类型
                    if container_type in ["Iterator", "Iterable"]:
                        return parse_type_with_context(element_type_str)

        except Exception:
            pass

        return None

    def _get_cached_type(self, node: IRNode) -> Optional[TypeInfo]:
        """
        获取IR节点的缓存类型

        Args:
            node: IR节点

        Returns:
            缓存的类型信息，如果没有缓存则返回None
        """
        return node.get_extension_param("inferred_type")

    def _cache_type_info(self, node: IRNode, type_info: TypeInfo | None) -> None:
        """将类型信息缓存到IR节点中

        Args:
            node: IR节点
            type_info: 要缓存的类型信息
        """
        if not type_info or type_info.kind == TypeKind.UNKNOWN:
            # raise ValueError(f"IR 节点 {node} 类型推断失败，结果不能为空")
            return

        old_type_info = self._get_cached_type(node)
        if old_type_info:
            if old_type_info == type_info:
                return

            if type_info.kind == TypeKind.ANY and old_type_info.kind != TypeKind.ANY:
                return

        node.set_extension_param("inferred_type", type_info)

    def _cache_symbol(self, node: IRNode, symbol: Symbol):
        if not symbol:
            return
        node.set_symbol(symbol)

    def infer_type(self, node: IRNode, context: InferenceContext) -> TypeInfo:
        """类型推断入口点

        这是类型推断系统的唯一入口，根据节点类型自动分发到相应的推断方法。
        所有其他推断方法都应该通过这个入口调用。

        Args:
            node: 要推断类型的IR节点
            context: 推断上下文

        Returns:
            推断出的类型信息，如果推断失败返回None
        """
        # 特殊处理：对于 IRName 节点，如果上下文中有类型收窄信息，跳过缓存
        # 这样可以确保使用收窄后的类型
        if isinstance(node, IRName) and node.id in context.narrowed_types:
            # 不使用缓存，重新推导以应用类型收窄
            context.enter_node(node)
            try:
                inferred_type = self._infer_type_internal(node, context)
                # 注意：不缓存收窄后的类型，因为它只在特定上下文中有效
                context.exit_node()
                return inferred_type
            except Exception as e:
                context.exit_node()
                raise e

        # 优先从IR节点缓存中获取类型
        cached_type = self._get_cached_type(node)
        if cached_type is not None:
            return cached_type

        context.enter_node(node)
        try:
            inferred_type = self._infer_type_internal(node, context)
            self._cache_type_info(node, inferred_type)
            context.exit_node()
            return inferred_type
        except Exception as e:
            context.exit_node()
            raise e

    def _infer_type_internal(self, node: IRNode, context: InferenceContext) -> TypeInfo:
        """类型推断函数 - 基于配置表分发"""
        handler = self._inference_handlers.get(node.node_type)
        if handler:
            return handler(node, context)
        return TypeInfo.any()

    def _infer_constant_type(
        self, expr: IRConstant, context: InferenceContext
    ) -> Optional[TypeInfo]:
        """推断常量类型"""

        if hasattr(expr, "value"):
            type_info = None
            if isinstance(expr.value, bool):
                type_info = TypeInfo(TypeKind.PRIMITIVE, "bool")
            elif isinstance(expr.value, int):
                type_info = TypeInfo(TypeKind.PRIMITIVE, "int")
            elif isinstance(expr.value, float):
                type_info = TypeInfo(TypeKind.PRIMITIVE, "float")
            elif isinstance(expr.value, str):
                type_info = TypeInfo(TypeKind.PRIMITIVE, "str")
            elif expr.value is None:
                type_info = TypeInfo.none()

            # 标记为编译时常量
            if type_info:
                type_info.is_constant = True
                type_info.constant_value = expr.value
                return type_info

        return TypeInfo.unknown()

    def _infer_name_type(
        self, expr: IRName, context: InferenceContext
    ) -> Optional[TypeInfo]:
        """推断名称类型

        支持类型收窄：如果变量在当前上下文中被收窄，返回收窄后的类型
        """
        if not expr.id:
            return None

        # 1. 优先检查上下文中的类型收窄信息
        # 这会捕获在同一 if 分支内的收窄
        if expr.id in context.narrowed_types:
            narrowing_info = context.narrowed_types[expr.id]
            narrowed_type = narrowing_info.narrowed_type
            # 同时将收窄信息附加到节点上（用于代码生成）
            expr.set_narrowing_info(expr.id, narrowing_info)
            self._cache_type_info(expr, narrowed_type)
            return narrowed_type

        # 2. 向上查找祖先节点中的收窄信息（用于负向守卫）
        # 例如：if not num: break 之后，num 应该被收窄
        narrowing_info = self._find_narrowing_in_ancestors(expr)
        if narrowing_info:
            narrowed_type = narrowing_info.narrowed_type
            # 将收窄信息附加到节点上（用于代码生成）
            expr.set_narrowing_info(expr.id, narrowing_info)
            self._cache_type_info(expr, narrowed_type)
            return narrowed_type

        # 3. 这是使用点，查找符号获取类型
        symbol = expr.lookup_symbol(expr.id)
        if not symbol:
            return TypeInfo.any()

        # 如果符号已有类型信息，返回副本（避免修改原始类型信息）
        if symbol.type_info:
            # 注意：变量引用不是常量，即使初始值是常量
            type_info = copy(symbol.type_info)
            type_info.is_constant = False
            type_info.constant_value = None
            return type_info

        # 检查符号的 ir_node 是否已经有缓存的类型信息
        if symbol.ir_node:
            cached_type = self._get_cached_type(symbol.ir_node)
            if cached_type:
                # 注意：变量引用不是常量，即使初始值是常量
                # 返回副本并清除常量标记（避免修改原始类型信息）
                type_info = copy(cached_type)
                type_info.is_constant = False
                type_info.constant_value = None
                self._cache_type_info(expr, type_info)
                self._cache_symbol(expr, symbol)
                return type_info

            # 如果 symbol.ir_node 是 IRName 类型，避免递归推导
            # 这种情况下，说明符号还未完成初始化，返回 Any
            if isinstance(symbol.ir_node, IRName):
                return TypeInfo.any()

        # 由于采用了两遍遍历法，在推导返回值之前，函数体中的所有语句都已被推导
        # 因此这里可以安全地获取类型信息
        type_info = symbol.get_type_info(context)
        if not type_info:
            return TypeInfo.any()

        self._cache_type_info(expr, type_info)
        self._cache_symbol(expr, symbol)
        return type_info

    def _find_narrowing_in_ancestors(self, expr: IRName) -> Optional[TypeNarrowingInfo]:
        """向上查找祖先节点中的收窄信息（用于负向守卫）

        场景：if not num: break
             # 在 if 之后，num 应该被收窄
             total = total + num  # 这里的 num 应该查找到 if 节点上的收窄信息

        Args:
            expr: 变量名节点

        Returns:
            类型收窄信息，如果没有找到则返回 None
        """
        # 注意：此方法已被 _propagate_narrowing_to_siblings 取代
        # 保留此方法是为了向后兼容，但实际上不再需要向上查找
        # 因为收窄信息已经在 if 语句推导时附加到后续节点上了
        return None

    def _infer_call_type(
        self, expr: IRCall, context: InferenceContext
    ) -> Optional[TypeInfo]:
        return self._infer_call_type_inner(expr, context) or TypeInfo.none()

    def _infer_call_type_inner(
        self, expr: IRCall, context: InferenceContext
    ) -> Optional[TypeInfo]:
        """推断函数调用类型

        利用期望类型机制：为每个参数传递对应的参数类型作为期望类型
        """

        # 首先尝试获取函数的类型信息，以便为参数提供期望类型
        func_type_info = self._get_function_type_info(expr, context)

        # 推断位置参数类型，并为每个参数提供期望类型
        arg_types = []
        # 对于方法调用，第一个参数是 self，实际参数从索引 1 开始
        is_method_call = isinstance(expr.func, IRAttribute)
        for i, arg in enumerate(expr.args):
            # 为参数提供期望类型
            if func_type_info and func_type_info.args:
                # 如果是方法调用，参数索引需要 +1（跳过 self）
                param_index = i + 1 if is_method_call else i
                if param_index < len(func_type_info.args):
                    param_type = func_type_info.args[param_index]
                    arg_context = context.with_expected_type(param_type)
                    arg_type = self.infer_type(arg, arg_context)
                else:
                    arg_type = self.infer_type(arg, context)
            else:
                arg_type = self.infer_type(arg, context)

            arg_types.append(arg_type)

        # 【新增】检查参数类型兼容性（编译时类型检查）
        if func_type_info and func_type_info.args:
            for i, arg_type in enumerate(arg_types):
                # 获取期望的参数类型
                param_index = i + 1 if is_method_call else i
                if param_index < len(func_type_info.args):
                    expected_param_type = func_type_info.args[param_index]

                    # 获取参数名称（用于错误信息）
                    if i < len(expr.args):
                        arg_node = expr.args[i]
                        if isinstance(arg_node, IRName):
                            param_name = arg_node.id
                        else:
                            param_name = f"arg{i}"
                    else:
                        param_name = f"arg{i}"

                    # 检查类型兼容性
                    self._check_type_compatibility(
                        expected_param_type, arg_type, param_name, expr
                    )

        # 推断关键字参数类型
        # TODO: 未来可以扩展支持关键字参数的期望类型
        for keyword_name, keyword_value in expr.keywords:
            self.infer_type(keyword_value, context)

        # 推断可变参数 **kwargs
        if expr.starargs:
            self.infer_type(expr.starargs, context)

        if isinstance(expr.func, IRAttribute):
            # 处理方法调用，如 list.append(1)
            return self._infer_method_call_type(expr, arg_types, context)
        elif isinstance(expr.func, IRSubscript):
            # 处理参数化类型构造，如 set[int]()
            return self._infer_parameterized_constructor_call(expr, arg_types, context)
        elif isinstance(expr.func, IRName):
            # 处理函数调用，如 len(list)
            # 也包括类型构造，如 int(), set()
            func_name = expr.func.id

            # 先查找符号（不传 arg_types，避免对类型构造函数造成错误实例化）
            symbol_without_args = expr.lookup_symbol(func_name)

            # 如果是类型构造函数（CLASS），使用不带 args_types 的符号
            # 如果是普通函数，传递 arg_types 进行重载匹配
            if symbol_without_args and symbol_without_args.kind == SymbolKind.CLASS:
                symbol = symbol_without_args
            else:
                # 普通函数或找不到，使用带参数类型的查找
                symbol = (
                    expr.lookup_symbol(func_name, func_args=arg_types)
                    or symbol_without_args
                )

            if not symbol:
                # 如果找不到符号，返回 Any 类型而不是抛出异常
                # 这允许严格类型检查在后续阶段报告错误
                return TypeInfo.any()

            type_info = symbol.get_type_info(context)
            if not type_info:
                # 如果没有类型信息，返回 Any 类型
                return TypeInfo.any()

            self._cache_symbol(expr.func, symbol)
            if symbol.kind == SymbolKind.CLASS:
                # 类型构造器：需要处理泛型返回类型实例化
                # 例如：list(dict_keys[str]) 应该推导为 list[str]

                # 检查类型信息是否存在
                if not symbol.type_info:
                    return TypeInfo.any()

                # 优先级1：使用期望类型推导（如果有明确的期望类型且兼容）
                # 例如：s: set[int] = set() 应该推导为 set[int]
                if context.expected_type and self._is_compatible_generic_type(
                    symbol.type_info, context.expected_type
                ):
                    # 期望类型与构造类型兼容，使用期望类型（带具体类型参数）
                    self._cache_type_info(expr.func, context.expected_type)
                    return context.expected_type

                # 优先级2：从函数参数推导模板参数
                # 获取匹配的签名（用于模板参数提取）
                matching_sig = symbol.find_matching_signature(arg_types)

                # 如果有匹配的签名且返回类型包含模板参数，进行实例化
                if matching_sig and matching_sig.return_type:
                    # 解析返回类型字符串
                    return_type = self._parse_return_type(matching_sig.return_type)

                    # 如果返回类型包含模板参数，进行实例化
                    if return_type and self._has_template_params(
                        return_type, matching_sig.template_params or []
                    ):
                        instantiated_type = self._instantiate_constructor_return_type(
                            return_type, matching_sig, arg_types, expr
                        )
                        if instantiated_type:
                            self._cache_type_info(expr.func, instantiated_type)
                            return instantiated_type

                # 优先级3：回退到默认类型
                final_type = symbol.type_info
                self._cache_type_info(expr.func, final_type)
                return final_type

            self._cache_type_info(expr.func, type_info)

            # 泛型函数实例化：从参数类型中提取模板参数
            # 例如：min(iterable: Iterable[T_comparable]) -> T_comparable
            # 参数：set[int] -> 提取 T_comparable = int
            matching_sig = symbol.find_matching_signature(arg_types)
            if matching_sig:
                # 从参数类型中提取模板参数值
                template_values = self._extract_template_params_from_args(
                    matching_sig, arg_types, expr
                )
                if template_values:
                    # 存储到调用节点供代码生成使用
                    expr.set_extension_param("generic_type_params", template_values)

            # 泛型函数实例化：如果函数返回类型包含泛型参数，需要实例化
            # 从签名中获取原始返回类型（而不是从 type_info，后者可能已被处理）
            return_type = None
            if matching_sig and matching_sig.return_type:
                return_type = parse_type_with_context(
                    matching_sig.return_type, node=expr
                )

            # 回退：如果没有匹配签名，使用 type_info 的返回类型
            if not return_type:
                return_type = type_info.return_type

            # 优先从参数类型推导模板参数并实例化返回类型
            if return_type and matching_sig and template_values:
                # 使用从参数推导的模板参数实例化返回类型
                instantiated_type = self._substitute_template_params(
                    return_type, template_values
                )
                if instantiated_type and instantiated_type != return_type:
                    return instantiated_type

            # 备用方案：使用期望类型推导
            if return_type and context.expected_type:
                instantiated_type = self._instantiate_generic_return_type(
                    return_type, context.expected_type, expr
                )
                if instantiated_type:
                    return instantiated_type

            # async函数调用：将返回类型包装成result[T]
            if (
                return_type
                and symbol
                and symbol.ir_node
                and hasattr(symbol.ir_node, "is_async")
                and getattr(symbol.ir_node, "is_async", False)
            ):
                # 调用async函数返回result[T]
                return_type = TypeInfo(
                    kind=TypeKind.GENERIC,
                    name="result",
                    args=[return_type],
                    return_type=return_type,  # 保存原始返回类型
                )

            return return_type
        elif isinstance(expr.func, IRExpr):
            # 推断函数类型（用于复杂表达式）
            func_type = self.infer_type(expr.func, context)
            return_type = self._get_function_type(func_type, arg_types, context)
            if return_type:
                return return_type

        return None

    def _get_function_type_info(
        self, expr: IRCall, context: InferenceContext
    ) -> Optional[TypeInfo]:
        """获取函数的类型信息（用于提取参数类型）

        注意：这个方法只是为了获取参数类型，不进行完整的类型推导
        """
        if isinstance(expr.func, IRName):
            func_name = expr.func.id
            # 先尝试不带参数类型的查找（因为我们还没推导参数）
            symbol = expr.lookup_symbol(func_name)
            if symbol:
                # 对于类型构造调用，获取构造函数的函数类型（包含参数类型）
                if symbol.kind == SymbolKind.CLASS and symbol.signatures:
                    # 优先使用明确的类型注解（如 list[int]），而不是外部期望类型
                    explicit_type = self._extract_explicit_type_from_call(expr)
                    expected_type = (
                        explicit_type if explicit_type else context.expected_type
                    )
                    func_type_info = self._get_constructor_function_type(
                        symbol, len(expr.args), expected_type
                    )
                    if func_type_info:
                        return func_type_info

                # 对于非类型构造或无签名的情况，返回符号的类型信息
                return symbol.get_type_info(context)
        elif isinstance(expr.func, IRSubscript):
            # 处理 list[int](...) 这种显式类型构造调用
            func_name = None
            if isinstance(expr.func.value, IRName):
                func_name = expr.func.value.id
            if func_name:
                symbol = expr.lookup_symbol(func_name)
                if symbol and symbol.kind == SymbolKind.CLASS and symbol.signatures:
                    # 从 IRSubscript 中提取明确的类型（如 list[int]）
                    explicit_type = self._extract_type_from_subscript(expr.func, symbol)
                    if explicit_type:
                        func_type_info = self._get_constructor_function_type(
                            symbol, len(expr.args), explicit_type
                        )
                        if func_type_info:
                            return func_type_info
        elif isinstance(expr.func, IRAttribute):
            # 对于方法调用，获取方法符号的完整函数类型
            # 注意：不能使用 infer_type，因为它只返回返回类型，而我们需要参数类型
            # 先触发类型推导以确保符号被缓存
            self.infer_type(expr.func, context)
            # 然后从缓存的符号获取完整的函数类型
            cached_symbol = expr.func.get_extension_param("symbol")
            if cached_symbol and cached_symbol.type_info:
                return cached_symbol.type_info
            return None
        elif isinstance(expr.func, IRExpr):
            # 对于复杂表达式，推断其类型
            return self.infer_type(expr.func, context)

        return None

    def _extract_explicit_type_from_call(self, expr: IRCall) -> Optional[TypeInfo]:
        """从调用表达式中提取明确的类型注解（如 list[int]）

        Args:
            expr: 调用表达式

        Returns:
            明确的类型信息，如果没有则返回 None
        """
        # IRName 没有类型参数，返回 None
        return None

    def _extract_type_from_subscript(
        self, subscript: IRSubscript, symbol: Symbol
    ) -> Optional[TypeInfo]:
        """从 IRSubscript 中提取明确的类型信息（如 list[int]）

        Args:
            subscript: 下标节点（如 list[int]）
            symbol: 类型符号（如 list）

        Returns:
            类型信息（如 list[int]），如果无法提取则返回 None
        """
        # 获取类型名（如 "list"）
        type_name = None
        if isinstance(subscript.value, IRName):
            type_name = subscript.value.id
        elif isinstance(subscript.value, IRAttribute):
            # 处理 mc.list[int] 这种情况
            if isinstance(subscript.value.value, IRName):
                type_name = subscript.value.value.id
                attr = subscript.value.attr
                if attr != type_name:  # 如果属性名不同，可能需要命名空间前缀
                    # 暂时不支持命名空间类型
                    return None

        if not type_name or type_name != symbol.name:
            return None

        # 从 slice 中提取类型参数
        slice_node = subscript.slice
        type_args = []

        # 处理单个类型参数（如 list[int]）
        if isinstance(slice_node, IRName):
            type_arg_str = slice_node.id
            type_arg = parse_type_with_context(type_arg_str)
            if type_arg:
                type_args.append(type_arg)
        # 处理多个类型参数（如 dict[str, int]）
        elif isinstance(slice_node, IRTuple):
            for element in slice_node.elements:
                if isinstance(element, IRName):
                    type_arg_str = element.id
                    type_arg = parse_type_with_context(type_arg_str)
                    if type_arg:
                        type_args.append(type_arg)

        if type_args:
            return TypeInfo(TypeKind.GENERIC, type_name, args=type_args)

        return None

    def _get_constructor_function_type(
        self, symbol: Symbol, arg_count: int, expected_type: Optional[TypeInfo]
    ) -> Optional[TypeInfo]:
        """获取类型构造函数的函数类型信息

        根据参数数量和期望类型，选择合适的构造函数签名并应用模板参数替换。

        Args:
            symbol: 类型符号
            arg_count: 参数数量
            expected_type: 期望类型（用于强类型场景的模板参数推导）

        Returns:
            函数类型信息（包含参数类型），如果找不到合适的签名则返回 None
        """
        # 根据参数数量选择合适的签名
        for sig in symbol.signatures:
            required_params = len(sig.param_types) - len(sig.optional_params)
            if arg_count >= required_params and arg_count <= len(sig.param_types):
                # 构建模板参数替换字典
                template_substitutions = self._build_template_substitutions(
                    symbol, sig, expected_type
                )

                # 应用模板参数替换，获取函数类型信息
                func_type_info = sig.get_function_type_info(template_substitutions)
                if func_type_info:
                    return func_type_info

        return None

    def _build_template_substitutions(
        self, symbol: Symbol, sig, expected_type: Optional[TypeInfo]
    ) -> Optional[dict]:
        """构建模板参数替换字典

        根据期望类型或类型配置，构建模板参数到具体类型的映射。

        Args:
            symbol: 类型符号
            sig: 构造函数签名
            expected_type: 期望类型

        Returns:
            模板参数替换字典，如果不需要替换则返回 None
        """
        # 场景1：有期望类型（强类型场景）
        # 例如：v: list[int] = list([1, 2])，期望类型是 list[int]，提取出 T -> int
        if expected_type and expected_type.args:
            template_substitutions = {}
            for i, template_param in enumerate(sig.template_params or []):
                if i < len(expected_type.args):
                    arg_type = expected_type.args[i]
                    template_substitutions[template_param] = arg_type.name
            return template_substitutions if template_substitutions else None

        # 场景2：无期望类型（弱类型场景）
        # 例如：v = list([1, 2])，使用 type_substitution 配置（T -> Any）
        if (
            not expected_type
            and symbol.type_config
            and symbol.type_config.get("type_substitution")
        ):
            return symbol.type_config["type_substitution"]

        return None

    def _get_function_type(
        self, func_type: TypeInfo, arg_types: list[TypeInfo], context
    ):
        # 处理一般函数调用
        if func_type.kind == TypeKind.FUNCTION and func_type.return_type:
            return func_type.return_type

        # 如果是泛型函数，尝试实例化
        if func_type.kind == TypeKind.GENERIC:
            actual_type = self._infer_generic_call_type(func_type, arg_types, context)
            if actual_type:
                return actual_type.return_type

    def _infer_sformat_type(
        self, expr, context: InferenceContext
    ) -> Optional[TypeInfo]:
        """推断字符串格式化表达式类型

        f-string 和 str.format() 总是返回 str 类型
        """
        return TypeInfo(TypeKind.PRIMITIVE, "str")

    def _infer_lambda_type(
        self, expr: IRLambda, context: InferenceContext
    ) -> Optional[TypeInfo]:
        """推断 lambda 表达式类型，并完成闭包捕获分析

        支持双向类型推导：
        1. 自底向上：从 lambda 体推导返回类型
        2. 自顶向下：从期望类型（赋值目标、函数参数等）推导参数类型

        Args:
            expr: Lambda IR 节点
            context: 推断上下文（可能包含期望类型）

        Returns:
            Lambda 的函数类型信息
        """
        # 1. 推断参数类型（双向推导）
        param_types = []
        expected = context.expected_type

        # 检查是否有期望的函数类型（如 Callable[[int, int], int]）
        # 特殊处理：Callable 类型（kind=GENERIC, name="Callable"）
        has_expected_func = False
        expected_param_types = []
        expected_return = None

        if expected is not None:
            if expected.kind == TypeKind.FUNCTION:
                # 标准函数类型
                has_expected_func = expected.args is not None
                if has_expected_func:
                    expected_param_types = expected.args
                    expected_return = expected.return_type
            elif expected.kind == TypeKind.GENERIC and expected.name == "Callable":
                if expected.args:
                    expected_param_types = expected.args
                    has_expected_func = True

                if expected.return_type:
                    expected_return = expected.return_type

        for i, param in enumerate(expr.params):
            if has_expected_func and i < len(expected_param_types):
                # 优先：从期望类型推导（双向类型推导）
                param_type = expected_param_types[i]
            elif param.default_value is not None:
                # 次优先：从默认值推导参数类型
                try:
                    default_type = self.infer_type(param.default_value, context)
                    param_type = default_type if default_type else TypeInfo.any()
                except Exception:
                    # 推导失败：降级为 Any
                    param_type = TypeInfo.any()
            else:
                # 无期望类型和默认值：默认 Any
                param_type = TypeInfo.any()

            param_types.append(param_type)
            self._cache_type_info(param, param_type)

        # 2. 推断返回类型（expected_return 在上面已经提取了）
        # 无需再次提取

        if expr.body:
            if expected_return:
                body_context = context.with_expected_type(expected_return)
                return_type = self.infer_type(expr.body, body_context)
            else:
                return_type = self.infer_type(expr.body, context)
        else:
            return_type = TypeInfo.none()

        # 3. 闭包捕获分析
        captured_vars = self._analyze_lambda_captures(expr)
        expr.captured_vars = captured_vars

        # 4. 收集捕获变量的类型信息
        captured_var_types = {}
        for var_name in captured_vars:
            var_type = self._get_captured_var_type(var_name, expr)
            if var_type:
                captured_var_types[var_name] = var_type

        expr.set_extension_param("captured_var_types", captured_var_types)

        # 5. 构造 lambda 的函数类型
        lambda_type = TypeInfo(
            kind=TypeKind.FUNCTION,
            name="lambda",
            args=param_types,
            return_type=return_type,
        )

        return lambda_type

    def _analyze_lambda_captures(self, lambda_node: IRLambda) -> List[str]:
        """分析 lambda 捕获的变量（通过符号作用域判断）

        Args:
            lambda_node: Lambda IR 节点

        Returns:
            捕获的变量名列表
        """
        captured = []
        visited = set()  # 使用 id(node) 作为键

        # 获取参数名集合
        param_names = {p.name for p in lambda_node.params}

        # 遍历 lambda 体中的所有名称引用
        if lambda_node.body:
            for node in lambda_node.body.walk():
                node_id = id(node)
                if node_id in visited or not isinstance(node, IRName):
                    continue
                visited.add(node_id)

                var_name = node.id

                # 跳过参数和内置名称
                if var_name in param_names or var_name in {"True", "False", "None"}:
                    continue

                # 查找符号
                symbol = lambda_node.lookup_symbol(var_name)

                if not symbol:
                    continue

                # 通过符号的定义节点判断是否是闭包捕获
                # 如果符号的 ir_node 不在 lambda_node 的子树中，说明是外部变量
                if symbol.ir_node and not self._is_descendant_of(
                    symbol.ir_node, lambda_node
                ):
                    if var_name not in captured and symbol.kind in {
                        SymbolKind.VARIABLE,
                        SymbolKind.PARAMETER,
                        SymbolKind.CLOSURE_VARIABLE,
                    }:
                        captured.append(var_name)

        return captured

    def _is_descendant_of(self, node: IRNode, ancestor: IRNode) -> bool:
        """检查节点是否是祖先节点的后代

        Args:
            node: 要检查的节点
            ancestor: 祖先节点

        Returns:
            bool: 是否是后代节点
        """
        current = node.parent
        while current:
            if current == ancestor:
                return True
            current = current.parent
        return False

    def _get_captured_var_type(self, var_name: str, node: IRNode) -> Optional[TypeInfo]:
        """获取捕获变量的类型（通用方法，支持 Lambda 和嵌套函数）

        Args:
            var_name: 变量名
            node: Lambda 或函数节点

        Returns:
            变量的类型信息
        """
        symbol = node.lookup_symbol(var_name)
        if not symbol:
            return None

        # 优先使用符号的类型信息
        if symbol.type_info:
            return symbol.type_info

        # 如果符号没有类型，尝试从其 ir_node 获取
        if symbol.ir_node:
            inferred = symbol.ir_node.get_extension_param("inferred_type")
            if inferred:
                return inferred

            # 如果是参数节点，尝试从 type_annotation 解析
            if (
                hasattr(symbol.ir_node, "type_annotation")
                and symbol.ir_node.type_annotation  # type: ignore
            ):
                type_str = symbol.ir_node.type_annotation  # type: ignore
                parsed_type = parse_type(type_str, symbol.ir_node)
                if parsed_type:
                    return parsed_type

        return None

    def _infer_await_type(self, expr, context: InferenceContext) -> Optional[TypeInfo]:
        """推断 await 表达式类型

        await future<T> -> T

        Args:
            expr: Await IR 节点
            context: 推断上下文

        Returns:
            await表达式的类型（future的内部类型）
        """
        if not isinstance(expr, IRAwait):
            return TypeInfo.unknown()

        # 推断被await的表达式类型
        value_type = self.infer_type(expr.value, context)

        if not value_type:
            return TypeInfo.unknown()

        # 如果是Future类型或result类型，提取内部类型
        if value_type.name in ["Future", "future", "result", "Result"]:
            if value_type.args and len(value_type.args) > 0:
                # Future[T] | result[T] -> T
                return value_type.args[0]
            else:
                # Future/result (无类型参数) -> void
                return TypeInfo.none()

        # 如果不是Future/result类型，可能是类型推导失败，返回unknown
        return TypeInfo.unknown()

    def _is_nested_function(self, func_node: IRFunctionNode) -> bool:
        """判断是否为嵌套函数

        Args:
            func_node: 函数节点

        Returns:
            bool: 是否为嵌套函数
        """
        parent = func_node.parent
        while parent:
            if isinstance(parent, (IRFunctionNode, IRMethodNode)):
                return True
            parent = parent.parent
        return False

    def _analyze_function_captures(self, func_node: IRFunctionNode) -> List[str]:
        """分析嵌套函数捕获的变量（复用 Lambda 逻辑 95%）

        Args:
            func_node: 函数节点

        Returns:
            捕获的变量名列表
        """
        captured = []
        visited = set()  # 使用 id(node) 作为键

        # 获取参数名集合
        param_names = {p.name for p in func_node.params}

        # 遍历函数体中的所有名称引用
        if func_node.body:
            for node in func_node.body.walk():
                node_id = id(node)
                if node_id in visited or not isinstance(node, IRName):
                    continue
                visited.add(node_id)

                var_name = node.id

                # 跳过参数和内置名称
                if var_name in param_names or var_name in {"True", "False", "None"}:
                    continue

                # 查找符号
                symbol = func_node.lookup_symbol(var_name)

                if not symbol:
                    continue

                # 通过符号的定义节点判断是否是闭包捕获
                # 如果符号的 ir_node 不在 func_node 的子树中，说明是外部变量
                if symbol.ir_node and not self._is_descendant_of(
                    symbol.ir_node, func_node
                ):
                    if var_name not in captured and symbol.kind in {
                        SymbolKind.VARIABLE,
                        SymbolKind.PARAMETER,
                        SymbolKind.CLOSURE_VARIABLE,
                    }:
                        captured.append(var_name)

        return captured

    def _determine_lambda_usage_mode(self, lambda_node: IRLambda) -> str:
        """确定 lambda 使用模式

        Args:
            lambda_node: Lambda 节点

        Returns:
            使用模式 ("extension" | "cpp_lambda")
        """
        # 检查是否是立即调用（父节点是 Call）
        parent = lambda_node.parent
        if isinstance(parent, IRCall) and parent.func == lambda_node:
            # 立即调用，可以使用零开销 C++ lambda
            # 但前提是没有捕获变量或捕获的都是基础类型
            if not lambda_node.captured_vars:
                return "cpp_lambda"

        # 其他情况使用 extension 模式（可存储）
        return "extension"

    def _determine_lambda_storage_mode(self, lambda_node: IRLambda) -> str:
        """确定 lambda 存储模式（栈分配 vs 堆分配）

        Args:
            lambda_node: Lambda 节点

        Returns:
            存储模式 ("stack" | "heap")
        """
        # 规则1：立即调用已经优化为 cpp_lambda，不需要栈优化
        if lambda_node.usage_mode == "cpp_lambda":
            return "heap"  # cpp_lambda 不需要单独的存储模式

        # 规则2：检查是否在异步函数中（预留，未来支持 async/await）
        containing_func = self._get_containing_function(lambda_node)
        if containing_func and getattr(containing_func, "is_async", False):
            return "heap"  # 异步函数中强制堆分配

        # 规则3：逃逸分析 - 检查 lambda 的所有使用点
        escape_info = self._analyze_lambda_escape(lambda_node)

        if escape_info["escapes_to_any"]:
            return "heap"  # 赋值给 Any 类型

        if escape_info["stored_in_container"]:
            return "heap"  # 存储到 list/dict/set

        if escape_info["escapes_scope"]:
            return "heap"  # 从函数返回或作为 Any 参数

        # 规则4：默认栈分配（安全且高效）
        return "stack"

    def _get_containing_function(self, node):
        """获取包含节点的函数"""
        current = node.parent
        while current:
            if isinstance(current, IRFunctionNode):
                return current
            current = current.parent
        return None

    def _analyze_lambda_escape(self, lambda_node: IRLambda) -> dict:
        """分析 lambda 是否逃逸

        Returns:
            dict: {
                'escapes_to_any': bool,      # 是否赋值给 Any
                'stored_in_container': bool, # 是否存储到容器
                'escapes_scope': bool        # 是否逃逸出作用域
            }
        """
        info = {
            "escapes_to_any": False,
            "stored_in_container": False,
            "escapes_scope": False,
        }

        # 查找 lambda 的所有使用点
        parent = lambda_node.parent

        if not parent:
            return info

        # 情况1：赋值语句
        if isinstance(parent, IRAssign):
            # 检查目标类型
            target = parent.get_target_expr()
            if target:
                target_type = target.get_extension_param("inferred_type")
                if target_type and target_type.kind == TypeKind.ANY:
                    info["escapes_to_any"] = True

        # 情况2：容器中（list/dict/set 字面量）
        if isinstance(parent, (IRList, IRDict, IRSet)):
            info["stored_in_container"] = True

        # 情况3：从函数返回
        if isinstance(parent, IRReturn):
            func = self._get_containing_function(lambda_node)
            if func:
                return_type = func.get_extension_param("return_type")
                if not return_type or return_type.kind == TypeKind.ANY:
                    info["escapes_scope"] = True

        # 情况4：作为参数传递
        if isinstance(parent, IRCall):
            # 获取参数位置
            param_index = None
            for i, arg in enumerate(parent.args):
                if arg == lambda_node:
                    param_index = i
                    break

            if param_index is not None:
                # 获取被调用函数的参数类型
                param_type = self._get_call_param_type(parent, param_index)
                if param_type and param_type.kind == TypeKind.ANY:
                    info["escapes_to_any"] = True

        return info

    def _get_call_param_type(
        self, call_node: "IRCall", param_index: int
    ) -> Optional[TypeInfo]:
        """获取函数调用的参数类型"""
        # 获取被调用的函数
        func_type = call_node.func.get_extension_param("inferred_type")

        if func_type and func_type.args and param_index < len(func_type.args):
            return func_type.args[param_index]

        return None

    def _infer_class_attribute_type(
        self, obj_type: TypeInfo, expr: IRAttribute, context: InferenceContext
    ) -> Optional[TypeInfo]:
        # 检查成员是否已经推导过类型了
        attr = expr.attr
        if attr in obj_type.attributes and obj_type.attributes[attr].type_info:
            return obj_type.attributes[attr].type_info
        elif attr in obj_type.methods:
            type_info = obj_type.methods[attr].type_info
            if type_info and type_info.return_type:
                return type_info.return_type

        class_symbol = expr.lookup_symbol(obj_type.name)
        assert class_symbol, f"类 {obj_type.name} 未定义"
        assert class_symbol.ir_node, f"类 {obj_type.name} 没有对应的IR节点"
        attr_symbol = class_symbol.ir_node.lookup_symbol(attr)
        assert attr_symbol, f"类 {obj_type.name} 没有成员 {attr}"
        assert attr_symbol.ir_node, f"类 {obj_type.name} 的成员 {attr} 没有对应的IR节点"
        type_info = attr_symbol.type_info
        if not type_info:
            type_info = self.infer_type(attr_symbol.ir_node, context)
            attr_symbol.set_type_info(type_info)

        # 缓存到类类型中
        if attr_symbol.kind == SymbolKind.METHOD:
            obj_type.methods[attr] = attr_symbol
            return type_info.return_type
        elif attr_symbol.kind == SymbolKind.ATTRIBUTE:
            obj_type.attributes[attr] = attr_symbol
            return type_info

    def _infer_attribute_type(
        self, expr: IRAttribute, context: InferenceContext
    ) -> Optional[TypeInfo]:
        """推断属性访问类型"""
        # 推断对象类型
        obj_type = self.infer_type(expr.value, context)
        if not obj_type:
            return None

        if obj_type.kind == TypeKind.CLASS:
            return self._infer_class_attribute_type(obj_type, expr, context)
        elif obj_type.name == "dict":
            # 处理字典类型的属性访问
            return self._infer_dict_attribute_type(obj_type, expr, context)
        else:
            method_name = expr.attr
            symbol = expr.lookup_symbol(method_name, owner_type=obj_type)
            if symbol and symbol.type_info:
                self._cache_symbol(expr, symbol)
                return symbol.type_info

        return None

    def _infer_dict_attribute_type(
        self, dict_type: TypeInfo, expr: IRAttribute, context: InferenceContext
    ) -> Optional[TypeInfo]:
        """推断字典类型的属性访问"""

        # 尝试从字典变量的定义中获取属性类型（字面量追踪）
        if isinstance(expr.value, IRName):
            var_symbol = expr.value.lookup_symbol(expr.value.id)
            assert var_symbol, f"变量 {expr.value.id} 未定义"

            # 符号的 ir_node 指向 IRName，需要通过 parent 找到 IRAssign
            assign_node = None
            if var_symbol.ir_node and isinstance(var_symbol.ir_node, IRName):
                if isinstance(var_symbol.ir_node.parent, IRAssign):
                    assign_node = var_symbol.ir_node.parent
            elif isinstance(var_symbol.ir_node, IRAssign):
                # 向后兼容：万一有些符号直接指向 IRAssign
                assign_node = var_symbol.ir_node

            if assign_node:
                if assign_node.value and isinstance(assign_node.value, IRDict):
                    # 在字典字面量中查找属性
                    attr_value = self._get_dict_attribute_value(
                        assign_node.value, expr.attr, context
                    )
                    if attr_value:
                        return self.infer_type(attr_value, context)

        # 如果无法从字典字面量推断，返回字典值类型
        if dict_type.args and len(dict_type.args) >= 2:
            return dict_type.args[1]

        return TypeInfo.any()

    def _infer_method_call_type(
        self,
        node: IRCall,
        arg_types: List[TypeInfo],
        context: InferenceContext,
    ) -> Optional[TypeInfo]:
        """推断方法调用类型，特别处理mutating方法对容器类型的影响

        支持三种方法调用：
        1. expr.method()  - 表达式方法调用（如 ensure_future().get()）
        2. obj.method()   - 实例方法调用（object_name 是变量）
        3. Class.method() - 类方法/静态方法调用（object_name 是类型）
        """

        object_name = node.get_object_name()
        method_name = node.get_func_name()
        if not method_name:
            return None

        # 分支1: 处理对象是表达式的情况（如 [1, 2, 3].count(1) 或 ensure_future().get()）
        if not object_name:
            return self._infer_expression_method_call(
                node, method_name, arg_types, context
            )

        # 分支2: 处理对象是模块的情况（如 copy.deepcopy）
        module_result = self._try_infer_module_function_call(
            node, object_name, method_name, arg_types, context
        )
        if module_result is not None:
            return module_result

        # 分支3: 处理对象是类或变量的情况
        return self._infer_named_object_method_call(
            node, object_name, method_name, arg_types, context
        )

    def _infer_expression_method_call(
        self,
        node: IRCall,
        method_name: str,
        arg_types: List[TypeInfo],
        context: InferenceContext,
    ) -> Optional[TypeInfo]:
        """推断表达式对象的方法调用类型（如 ensure_future().get()）

        Args:
            node: 调用节点
            method_name: 方法名
            arg_types: 参数类型列表
            context: 推断上下文

        Returns:
            方法返回类型
        """
        if not isinstance(node.func, IRAttribute):
            return None

        # 推导对象表达式的类型
        object_expr = node.func.value
        object_type = self.infer_type(object_expr, context)
        if not object_type:
            return None

        # 尝试通过作用域查找类符号（支持 stub 导入的类型）
        cls_symbol = node.lookup_symbol(object_type.name)

        # 如果找不到类符号或类符号没有 IR 节点（说明是 builtin 类型）
        if not cls_symbol or not cls_symbol.ir_node:
            # 对于 builtin 类型（如 list, dict），使用全局注册表查找方法
            return self._lookup_builtin_method(
                object_type, method_name, arg_types, node
            )

        # 找到了有 IR 节点的类符号（stub 类型或用户自定义类型）
        # 通过 IR 节点查找方法
        return self._lookup_method_from_class_ir(
            cls_symbol, object_type, method_name, arg_types, node, context
        )

    def _try_infer_module_function_call(
        self,
        node: IRCall,
        object_name: str,
        method_name: str,
        arg_types: List[TypeInfo],
        context: InferenceContext,
    ) -> Optional[TypeInfo]:
        """尝试推断模块函数调用（如 copy.deepcopy）

        Args:
            node: 调用节点
            object_name: 对象名称
            method_name: 方法名
            arg_types: 参数类型列表
            context: 推断上下文

        Returns:
            函数返回类型，如果不是模块调用则返回 None
        """
        object_symbol = node.lookup_symbol(object_name, symbol_kinds=method_symbols)
        if not object_symbol or object_symbol.kind != SymbolKind.MODULE:
            return None

        import_node: IRImportNode = cast(IRImportNode, object_symbol.ir_node)
        resolved_module = import_node.resolved_modules.get(object_name)
        if not resolved_module:
            return None

        func_symbol = resolved_module.lookup_symbol(method_name, func_args=arg_types)
        if not func_symbol or not func_symbol.type_info:
            return None

        self._cache_type_info(node.func, func_symbol.type_info)
        self._cache_symbol(node.func, func_symbol)

        # 对于泛型函数（如 copy.copy(list[T]) -> list[T]）
        # 需要从参数类型中提取模板参数并替换返回类型
        return_type = func_symbol.type_info.return_type
        if return_type and arg_types:
            # 查找匹配的签名以获取模板参数映射
            matching_sig = func_symbol.find_matching_signature(arg_types)
            if matching_sig and matching_sig.return_type:
                # 从第一个参数推导返回类型（对于 copy.copy 等一元函数）
                if len(arg_types) > 0:
                    first_arg_type = arg_types[0]
                    # 如果返回类型和参数类型的基础类型相同（如都是 list）
                    # 则替换返回类型中的泛型参数
                    if return_type.name == first_arg_type.name:
                        return first_arg_type

        return return_type

    def _infer_named_object_method_call(
        self,
        node: IRCall,
        object_name: str,
        method_name: str,
        arg_types: List[TypeInfo],
        context: InferenceContext,
    ) -> Optional[TypeInfo]:
        """推断命名对象的方法调用（obj.method() 或 Class.method()）

        Args:
            node: 调用节点
            object_name: 对象名称
            method_name: 方法名
            arg_types: 参数类型列表
            context: 推断上下文

        Returns:
            方法返回类型
        """
        object_symbol = node.lookup_symbol(object_name, symbol_kinds=method_symbols)
        if not object_symbol:
            return None

        # 可能是类型的构造函数
        if object_symbol.kind == SymbolKind.FUNCTION:
            type_symbol = node.lookup_symbol(
                object_name, symbol_kinds=[SymbolKind.CLASS]
            )
            if type_symbol and type_symbol.kind == SymbolKind.CLASS:
                object_symbol = type_symbol

        # 根据 object_symbol 的类型设置 cls_symbol 和 object_type
        cls_symbol = None
        object_type = None

        if object_symbol.kind == SymbolKind.CLASS:
            # 类方法调用：Class.method()
            cls_symbol = object_symbol
            object_type = object_symbol.get_type_info(context)
            # 如果类型还没有推导过，先推导类类型
            if not object_type and cls_symbol.ir_node:
                from mcpy.ir.declarations.class_node import IRClassNode

                if isinstance(cls_symbol.ir_node, IRClassNode):
                    object_type = self._infer_class_type(cls_symbol.ir_node, context)
                    object_symbol.set_type_info(object_type)
            assert object_type, f"找不到类 {object_name} 的类型信息"

            # 对于 builtin 类型（如 dict, list），直接使用 owner_type 查找方法
            # 因为它们没有 ir_node，但在符号表中有方法配置
            if not object_symbol.ir_node:
                # builtin 类型的类方法调用（如 dict.fromkeys）
                return self._lookup_builtin_class_method(
                    object_type, object_name, method_name, arg_types, node
                )
        elif (
            object_symbol.kind == SymbolKind.VARIABLE
            or object_symbol.kind == SymbolKind.PARAMETER
        ):
            # 实例方法调用：obj.method()
            if isinstance(object_symbol.ir_node, Parameter):
                object_type = self._infer_parameter_type(object_symbol.ir_node, context)
            else:
                object_type = object_symbol.get_type_info(context)
            assert object_type, f"找不到变量 {object_name} 的类型"

            # 首先尝试通过IR查找类符号（包括GENERIC类型的stub类）
            cls_symbol = node.lookup_symbol(object_type.name)

            # 对于builtin类型（无IR节点），走builtin方法查找路径
            if not cls_symbol or not cls_symbol.ir_node:
                # 对于内置类型的实例方法调用（如 list.index, str.upper 等）
                return_type = self._lookup_builtin_method(
                    object_type, method_name, arg_types, node
                )
                if return_type:
                    return return_type

                # 注册表中找不到，尝试从stub类的IR节点中查找
                cls_symbol = node.lookup_symbol(object_type.name)
                if not cls_symbol or not cls_symbol.ir_node:
                    # 彻底找不到，返回unknown
                    return TypeInfo.unknown()
        else:
            raise TypeError(f"{object_name} 不是类或变量")

        # 对于用户自定义类或stub类，需要 ir_node
        # 到这里，cls_symbol 和 object_type 应该已经被设置好了
        if not cls_symbol or not cls_symbol.ir_node:
            # 找不到类的IR节点，无法推导方法类型，返回unknown
            return TypeInfo.unknown()

        # 通过类的 IR 节点查找方法
        return self._lookup_method_from_class_ir(
            cls_symbol,
            object_type,
            method_name,
            arg_types,
            node,
            context,
            object_symbol,
        )

    def _lookup_builtin_method(
        self,
        object_type: TypeInfo,
        method_name: str,
        arg_types: List[TypeInfo],
        node: IRCall,
    ) -> Optional[TypeInfo]:
        """从全局注册表查找 builtin 类型的实例方法

        Args:
            object_type: 对象类型
            method_name: 方法名
            arg_types: 参数类型列表
            node: 调用节点

        Returns:
            方法返回类型
        """
        registry = get_global_registry()
        type_str = build_type_signature(object_type)

        symbol = registry.lookup_instance_method(
            type_str,  # 完整类型签名
            method_name,  # 方法名
            arg_types,  # 参数类型列表
        )

        # 如果找不到实例化的方法，尝试查找泛型版本（如 list.append）
        if not symbol and object_type.kind == TypeKind.GENERIC:
            base_type_str = object_type.name
            symbol = registry.lookup_instance_method(
                base_type_str,  # 基础类型名（如 "list"）
                method_name,  # 方法名
                arg_types,  # 参数类型列表
            )

        if symbol and symbol.type_info:
            method_type = symbol.type_info
            self._cache_type_info(node.func, method_type)
            self._cache_symbol(node.func, symbol)
            # 替换返回类型中的泛型参数
            return self._substitute_generic_params(method_type.return_type, object_type)

        return None

    def _lookup_builtin_class_method(
        self,
        object_type: TypeInfo,
        object_name: str,
        method_name: str,
        arg_types: List[TypeInfo],
        node: IRCall,
    ) -> Optional[TypeInfo]:
        """从全局注册表查找 builtin 类型的类方法

        Args:
            object_type: 对象类型
            object_name: 对象名称
            method_name: 方法名
            arg_types: 参数类型列表
            node: 调用节点

        Returns:
            方法返回类型
        """
        registry = get_global_registry()
        symbol = registry.lookup_class_method(
            object_type.name,  # 类型名（如 "dict"）
            method_name,  # 方法名（如 "fromkeys"）
            arg_types,  # 参数类型列表
        )

        if not symbol or not symbol.type_info:
            raise TypeError(f"找不到 {object_name}.{method_name} 的类型信息")

        method_type = symbol.type_info
        self._cache_type_info(node.func, method_type)
        self._cache_symbol(node.func, symbol)
        # 替换返回类型中的泛型参数
        return self._substitute_generic_params(method_type.return_type, object_type)

    def _lookup_method_from_class_ir(
        self,
        cls_symbol: Symbol,
        object_type: TypeInfo,
        method_name: str,
        arg_types: List[TypeInfo],
        node: IRCall,
        context: InferenceContext,
        object_symbol: Optional[Symbol] = None,
    ) -> Optional[TypeInfo]:
        """从类的 IR 节点查找方法（适用于 stub 类型和用户自定义类型）

        Args:
            cls_symbol: 类符号（必须有 ir_node）
            object_type: 对象类型
            method_name: 方法名
            arg_types: 参数类型列表
            node: 调用节点
            context: 推断上下文
            object_symbol: 对象符号（如果有）

        Returns:
            方法返回类型
        """
        # 确保类符号有 IR 节点（调用者应该保证）
        assert cls_symbol.ir_node, f"类符号 {cls_symbol.name} 缺少 IR 节点"

        # 获取对象类型（self 的类型）
        if object_symbol and object_symbol.kind == SymbolKind.CLASS:
            # 直接使用类名（类方法调用）
            self_type = TypeInfo(kind=TypeKind.CLASS, name=cls_symbol.name)
        else:
            # 使用变量的类型（实例方法调用）
            self_type = object_type

        # 优先从 object_type.methods 中查找（如果已经推导过类类型）
        # 这样可以避免符号缓存未构建的问题
        method_symbol = None
        if object_type:
            method_symbol = object_type.methods.get(method_name)

        # 如果没找到，尝试从类的符号缓存中查找
        if not method_symbol:
            method_symbol = cls_symbol.ir_node.lookup_symbol(
                method_name,
                owner_type=self_type,
                func_args=arg_types,
            )

        # 如果还是没找到，尝试静态方法（不包含 self 类型）
        if not method_symbol:
            method_symbol = cls_symbol.ir_node.lookup_symbol(
                method_name, func_args=arg_types
            )

        # 如果还是没找到，尝试从class_type.methods中查找（不考虑参数类型）
        if not method_symbol and object_type and object_type.kind == TypeKind.CLASS:
            method_symbol = object_type.methods.get(method_name)

        if not method_symbol:
            # 构建友好的错误消息
            object_desc = object_type.name if object_type else "unknown"
            raise TypeError(f"{object_desc} 没有成员 {method_name}")

        method_type = method_symbol.get_type_info(context)
        if not method_type:
            object_desc = object_type.name if object_type else "unknown"
            raise TypeError(f"找不到方法 {object_desc}.{method_name} 的类型信息")

        self._cache_type_info(node.func, method_type)
        self._cache_symbol(node.func, method_symbol)
        # 替换返回类型中的泛型参数
        return self._substitute_generic_params(method_type.return_type, object_type)

    def _substitute_generic_params(
        self, return_type: Optional[TypeInfo], object_type: Optional[TypeInfo]
    ) -> Optional[TypeInfo]:
        """替换返回类型中的泛型参数

        例如：
        - object_type 是 list[int]，return_type 是 T，则返回 int
        - object_type 是 dict_items[int, str]，return_type 是 tuple[K, V]，则返回 tuple[int, str]
        """
        if not return_type:
            return return_type

        # 如果返回类型是类型参数（如 T, K, V）
        if return_type.kind in [TypeKind.TEMPLATE, TypeKind.TYPE_PARAM]:
            # 需要从 object_type 中找到对应的实际类型
            if object_type:
                # 首先，需要获取 object_type 的模板参数名列表
                from mcpy.symbol_registry import get_global_registry

                registry = get_global_registry()
                # 查找基础类型符号（带类型参数的实例化类型）
                type_symbol = registry.lookup_type_symbol(
                    object_type.name, object_type.args
                )

                if type_symbol and type_symbol.type_config:
                    # 获取模板参数名（如 ['K', 'V']）
                    template_params = type_symbol.type_config.get("generic_params", [])

                    # 查找 return_type.name 在模板参数中的位置
                    if return_type.name in template_params:
                        param_index = template_params.index(return_type.name)
                        # 返回对应的实际类型参数
                        if object_type.args and param_index < len(object_type.args):
                            return object_type.args[param_index]

                # 回退：如果是简单的 T，返回第一个类型参数
                if (
                    return_type.name == "T"
                    and object_type.args
                    and len(object_type.args) > 0
                ):
                    return object_type.args[0]

        # 如果返回类型是泛型类型（如 list[T]、tuple[K, V]）
        if return_type.args:
            # 递归替换类型参数
            new_args = []
            for arg in return_type.args:
                new_arg = self._substitute_generic_params(arg, object_type)
                new_args.append(new_arg)

            # 创建新的类型信息
            new_type = TypeInfo(
                kind=return_type.kind,
                name=return_type.name,
                module=return_type.module,
                args=new_args,
            )
            return new_type

        return return_type

    def _type_matches_for_method(
        self, obj_type: TypeInfo, expected_type_str: str
    ) -> bool:
        """检查对象类型是否匹配方法的期望类型"""
        # 简单的类型匹配逻辑
        if obj_type.name == expected_type_str:
            return True

        # 处理泛型类型匹配，如 list[int] 匹配 list[T]
        if "[" in expected_type_str and "]" in expected_type_str:
            expected_base = expected_type_str[: expected_type_str.index("[")]
            return obj_type.name == expected_base

        return False

    def _infer_property_type(
        self, node: IRPropertyNode, context: InferenceContext
    ) -> TypeInfo:
        """推断属性类型"""
        # 如果有类型注解，解析类型注解
        if node.type_annotation:
            return parse_type(node.type_annotation, node) or TypeInfo.any()

        # 如果有关联的赋值语句，从中推断类型
        assignment = getattr(node, "associated_assignment", None)
        if assignment and getattr(assignment, "value", None):
            return self.infer_type(getattr(assignment, "value"), context)

        # 默认返回Any类型
        return TypeInfo.any()

    def _infer_binop_type(
        self, expr: IRBinOp, context: InferenceContext
    ) -> Optional[TypeInfo]:
        """推断二元运算类型"""

        left_type = self.infer_type(expr.left, context)
        self._cache_type_info(expr.left, left_type)

        right_type = self.infer_type(expr.right, context)
        self._cache_type_info(expr.right, right_type)

        # 处理算术运算
        op = expr.op
        if op in ["+", "-", "*", "/", "//", "%", "**"]:
            return self._infer_arithmetic_type(left_type, right_type, op)
        elif op in ["==", "!=", "<", "<=", ">", ">="]:
            return TypeInfo(TypeKind.PRIMITIVE, "bool")
        elif op in ["and", "or"]:
            return TypeInfo(TypeKind.PRIMITIVE, "bool")

        return None

    def _unwrap_optional_type(self, type_info: TypeInfo) -> TypeInfo:
        """解包 Optional[T] 类型，返回内层类型 T

        Args:
            type_info: 类型信息

        Returns:
            如果是 Optional[T]，返回 T；否则返回原类型
        """
        if type_info.name == "Optional" and type_info.args and len(type_info.args) > 0:
            return type_info.args[0]
        return type_info

    def _infer_arithmetic_type(
        self, left_type: TypeInfo, right_type: TypeInfo, op: str
    ) -> TypeInfo:
        """推断算术运算类型"""
        # 特殊处理：Optional[T] 在算术运算中的行为
        # Python: Optional[int] 在运算时如果不是 None，行为类似 int
        # C++: std::optional<int> 支持与 int 的算术运算
        left_base_type = self._unwrap_optional_type(left_type)
        right_base_type = self._unwrap_optional_type(right_type)

        # 数值类型提升规则
        if left_base_type.name == "float" or right_base_type.name == "float":
            return TypeInfo(TypeKind.PRIMITIVE, "float")
        elif left_base_type.name == "int" and right_base_type.name == "int":
            if op in ["/", "Div"]:  # 除法总是返回float
                return TypeInfo(TypeKind.PRIMITIVE, "float")
            return TypeInfo(TypeKind.PRIMITIVE, "int")

        # 字符串连接
        if op in ["+"] and left_type.name == "str" and right_type.name == "str":
            return TypeInfo(TypeKind.PRIMITIVE, "str")

        # 字符串重复 (int * str 或 str * int)
        if op in ["*", "Mult"]:
            if left_type.name == "int" and right_type.name == "str":
                return TypeInfo(TypeKind.PRIMITIVE, "str")
            elif left_type.name == "str" and right_type.name == "int":
                return TypeInfo(TypeKind.PRIMITIVE, "str")

        # 处理容器类型的运算符重载
        # List 运算
        if (
            op in ["+", "Add"]
            and left_type.name == "list"
            and right_type.name == "list"
        ):
            # 合并元素类型
            if left_type.args and right_type.args:
                common_type = self._infer_common_type(
                    [left_type.args[0], right_type.args[0]], None
                )
                return TypeInfo(TypeKind.GENERIC, "list", args=[common_type])
            return TypeInfo(TypeKind.GENERIC, "list")

        # Set 集合运算
        # 支持：-, &, |, ^ 运算符
        if op in ["-", "&", "|", "^"]:
            # 检查是否是 set 类型（包括 Any 类型的 set）
            left_is_set = left_type.name == "set" or (left_type.kind == TypeKind.ANY)
            right_is_set = right_type.name == "set" or (right_type.kind == TypeKind.ANY)

            if left_is_set and right_is_set:
                # set 运算：结果类型与操作数相同
                if left_type.name == "set" and left_type.args:
                    # 强类型 set：保持元素类型
                    return left_type
                elif right_type.name == "set" and right_type.args:
                    # 右操作数有类型信息
                    return right_type
                else:
                    # 弱类型 set（Any）：返回弱类型 set
                    return TypeInfo(TypeKind.GENERIC, "set")

        return TypeInfo.unknown()

    def _infer_unaryop_type(
        self, expr: IRUnaryOp, context: InferenceContext
    ) -> Optional[TypeInfo]:
        """推断一元运算类型"""
        operand_type = self.infer_type(expr.operand, context)
        if not operand_type:
            return None

        # IR节点的op是字符串，不是AST对象
        op = expr.op

        if op == "not":
            return TypeInfo(TypeKind.PRIMITIVE, "bool")
        elif op in ["pos", "neg"]:
            # 保持数值类型
            if operand_type.name in ["int", "float"]:
                return operand_type

        return operand_type

    def _infer_compare_type(
        self, expr: IRCompare, context: InferenceContext
    ) -> Optional[TypeInfo]:
        """推断比较运算类型"""
        # 主动推断左操作数类型并设置到extension_params
        left_type = self.infer_type(expr.left, context)
        if left_type:
            self._cache_type_info(expr.left, left_type)

        # 主动推断右操作数类型并设置到extension_params
        for comp in expr.comparators:
            comp_type = self.infer_type(comp, context)
            if comp_type:
                self._cache_type_info(comp, comp_type)

        # 比较运算总是返回bool类型
        return TypeInfo(TypeKind.PRIMITIVE, "bool")

    def _infer_boolop_type(
        self, expr: IRBoolOp, context: InferenceContext
    ) -> Optional[TypeInfo]:
        """推断布尔运算类型"""
        # 布尔运算(and/or)总是返回bool类型
        return TypeInfo(TypeKind.PRIMITIVE, "bool")

    def _infer_subscript_type(
        self, expr: IRSubscript, context: InferenceContext
    ) -> Optional[TypeInfo]:
        """推断下标访问类型"""

        expected_type = context.expected_type
        container_type = self.infer_type(expr.value, context)
        if not container_type:
            return None

        # 切片访问保持容器类型
        if isinstance(expr.slice, IRSlice):
            if container_type.name == "list":
                if container_type.args:
                    return deepcopy(container_type)
                if (
                    expected_type
                    and expected_type.name == "list"
                    and expected_type.args
                ):
                    return deepcopy(expected_type)
                return TypeInfo(
                    TypeKind.GENERIC,
                    "list",
                    args=[TypeInfo.any()],
                )
            return deepcopy(container_type)

        # 尝试编译期常量求值
        constant_result = self._try_constant_evaluation(expr, context)
        if constant_result:
            return constant_result

        # 处理容器类型的元素访问
        if container_type.name == "list":
            if container_type.args:
                return container_type.args[0]  # 列表元素类型
            else:
                # 弱类型 list 返回 any
                return TypeInfo.any()

        elif container_type.name == "dict":
            if container_type.args and len(container_type.args) >= 2:
                return container_type.args[1]
            else:
                # 弱类型 dict 返回 any
                return TypeInfo.any()

        elif container_type.name == "str":
            return TypeInfo(TypeKind.PRIMITIVE, "str")  # 字符串索引返回字符

        elif container_type.name == "tuple" and container_type.args:
            # 元组索引，尝试推导精确类型
            index = None
            tuple_len = len(container_type.args)

            # 处理常量索引（正数）
            if isinstance(expr.slice, IRConstant) and isinstance(expr.slice.value, int):
                index = expr.slice.value
            # 处理负数索引（IRUnaryOp(op="neg", operand=IRConstant(value=1))）
            elif isinstance(expr.slice, IRUnaryOp) and expr.slice.op == "neg":
                if isinstance(expr.slice.operand, IRConstant) and isinstance(
                    expr.slice.operand.value, int
                ):
                    # 负数索引：-1 对应的正数索引是 len - 1
                    index = -(expr.slice.operand.value)

            if index is not None:
                # 处理负数索引：将其转换为对应的正数索引
                # 例如：-1 -> len - 1, -2 -> len - 2
                if index < 0:
                    index = tuple_len + index

                # 检查索引是否在有效范围内
                if 0 <= index < tuple_len:
                    return container_type.args[index]

            # 如果无法确定索引，返回联合类型
            return self._infer_common_type(container_type.args, context)

        return TypeInfo.unknown()

    def _try_constant_evaluation(
        self, expr: IRSubscript, context: InferenceContext
    ) -> Optional[TypeInfo]:
        """尝试编译期常量求值

        对于形如 dict_literal[key] 或 list_literal[index] 的表达式，
        如果容器和索引都是常量，则尝试在编译期求值并推导精确类型。
        """

        # 检查容器是否为变量引用
        if isinstance(expr.value, IRName):
            # 查找变量定义
            symbol = expr.value.lookup_symbol(expr.value.id)
            if symbol and symbol.ir_node and isinstance(symbol.ir_node, IRAssign):
                # 检查是否为字典赋值
                if symbol.ir_node.value and isinstance(symbol.ir_node.value, IRDict):
                    return self._evaluate_dict_subscript(
                        symbol.ir_node.value, expr.slice, context
                    )
                # 检查是否为列表赋值
                elif symbol.ir_node.value and isinstance(symbol.ir_node.value, IRList):
                    return self._evaluate_list_subscript(
                        symbol.ir_node.value, expr.slice, context
                    )

        # 检查容器是否为直接的字典或列表字面量
        elif isinstance(expr.value, IRDict):
            return self._evaluate_dict_subscript(expr.value, expr.slice, context)
        elif isinstance(expr.value, IRList):
            return self._evaluate_list_subscript(expr.value, expr.slice, context)

        # 检查是否为属性访问的下标，如 obj.attr[index]
        elif isinstance(expr.value, IRAttribute):
            return self._try_attribute_subscript_evaluation(
                expr.value, expr.slice, context
            )

        return None

    def _try_attribute_subscript_evaluation(
        self, attr_expr: IRAttribute, slice_expr: IRNode, context: InferenceContext
    ) -> Optional[TypeInfo]:
        """尝试对属性访问的下标进行编译期求值

        处理形如 obj.attr[index] 的表达式
        """
        # 检查是否为简单的变量属性访问
        if isinstance(attr_expr.value, IRName):
            # 查找对象变量
            obj_symbol = attr_expr.value.lookup_symbol(attr_expr.value.id)
            if (
                obj_symbol
                and obj_symbol.ir_node
                and isinstance(obj_symbol.ir_node, IRAssign)
            ):
                # 检查对象是否为字典字面量
                if obj_symbol.ir_node.value and isinstance(
                    obj_symbol.ir_node.value, IRDict
                ):
                    # 在字典中查找属性对应的值
                    attr_value = self._get_dict_attribute_value(
                        obj_symbol.ir_node.value, attr_expr.attr, context
                    )
                    if attr_value and isinstance(attr_value, IRList):
                        # 如果属性值是列表，进行下标求值
                        return self._evaluate_list_subscript(
                            attr_value, slice_expr, context
                        )
                    elif attr_value and isinstance(attr_value, IRDict):
                        # 如果属性值是字典，进行下标求值
                        return self._evaluate_dict_subscript(
                            attr_value, slice_expr, context
                        )

        return None

    def _get_dict_attribute_value(
        self, dict_expr: IRDict, attr_name: str, context: InferenceContext
    ) -> Optional[IRNode]:
        """从字典字面量中获取指定属性的值"""
        # 在字典中查找对应的键值对
        for dict_key, dict_value in zip(dict_expr.keys, dict_expr.values):
            if isinstance(dict_key, IRConstant) and dict_key.value == attr_name:
                return dict_value
        return None

    def _evaluate_dict_subscript(
        self, dict_expr: IRDict, slice_expr: IRNode, context: InferenceContext
    ) -> Optional[TypeInfo]:
        """求值字典下标访问"""
        # 检查索引是否为字符串常量
        if isinstance(slice_expr, IRConstant) and isinstance(slice_expr.value, str):
            key = slice_expr.value
            # 在字典中查找对应的键值对
            for dict_key, dict_value in zip(dict_expr.keys, dict_expr.values):
                if isinstance(dict_key, IRConstant) and dict_key.value == key:
                    # 推导值的类型
                    return self.infer_type(dict_value, context)
        return None

    def _evaluate_list_subscript(
        self, list_expr: IRList, slice_expr: IRNode, context: InferenceContext
    ) -> Optional[TypeInfo]:
        """求值列表下标访问"""
        # 检查索引是否为整数常量
        if isinstance(slice_expr, IRConstant) and isinstance(slice_expr.value, int):
            index = slice_expr.value
            # 检查索引是否在范围内
            if 0 <= index < len(list_expr.elements):
                # 推导对应元素的类型
                return self.infer_type(list_expr.elements[index], context)
        return None

    def _infer_list_type(
        self, expr: IRList, context: InferenceContext
    ) -> Optional[TypeInfo]:
        """推断列表字面量类型"""

        elements = expr.elements

        # 如果有期望类型（非空列表情况下也使用）
        if (
            context.expected_type
            and context.expected_type.name == "list"
            and context.expected_type.args
        ):
            expected_element_type = context.expected_type.args[0]
            # 推导所有元素的类型，传递期望的元素类型
            element_types = []
            element_context = context.with_expected_type(expected_element_type)
            for elt in elements:
                element_types.append(self.infer_type(elt, element_context))

            if element_types:
                # 检查期望类型是否包含模板参数（如 K, V）
                # 如果包含，应该从元素推导具体类型，而不是使用期望类型
                has_template_params = self._has_template_params_in_type(
                    context.expected_type
                )
                if has_template_params:
                    # 期望类型包含模板参数，使用从元素推导的具体类型
                    common_element_type = self._infer_common_type(
                        element_types, context
                    )
                    return TypeInfo(
                        TypeKind.GENERIC, "list", args=[common_element_type]
                    )
                # 期望类型是具体类型，返回期望类型
                return context.expected_type
            else:
                # 空列表，检查期望类型是否包含模板参数
                has_template_params = self._has_template_params_in_type(
                    context.expected_type
                )
                if has_template_params:
                    # 包含模板参数，无法推导，返回 list[Any]
                    return TypeInfo(TypeKind.GENERIC, "list")
                # 期望类型是具体类型，返回期望类型
                return context.expected_type

        # 没有期望类型的情况
        # 推断所有元素的类型
        element_types = []
        for elt in elements:
            element_types.append(self.infer_type(elt, context))

        if element_types:
            common_type = self._infer_common_type(element_types, context)
            return TypeInfo(TypeKind.GENERIC, "list", args=[common_type])

        # 无法推导，返回 list（等价于 list[Any]）
        return TypeInfo(TypeKind.GENERIC, "list")

    def _infer_dict_type(
        self, expr: IRDict, context: InferenceContext
    ) -> Optional[TypeInfo]:
        """推断字典字面量类型"""

        # 推断键和值的类型
        key_types = []
        value_types = []

        for key, value in zip(expr.keys, expr.values):
            key_type = self.infer_type(key, context)
            value_type = self.infer_type(value, context)
            key_types.append(key_type)
            value_types.append(value_type)

        if key_types and value_types:
            key_common_type = self._infer_common_type(key_types, context)
            value_common_type = self._infer_common_type(value_types, context)
            return TypeInfo(
                TypeKind.GENERIC, "dict", args=[key_common_type, value_common_type]
            )

        # 空字典：尝试从期望类型推导
        if context.expected_type:
            # 如果期望类型是 dict[K, V]，则使用 K, V 作为键值类型
            if (
                context.expected_type.name == "dict"
                and context.expected_type.args
                and len(context.expected_type.args) >= 2
            ):
                return context.expected_type

        # 无法推导，返回 dict（等价于 dict[Any, Any]）
        return TypeInfo(TypeKind.GENERIC, "dict")

    def _infer_tuple_type(
        self, expr: IRTuple, context: InferenceContext
    ) -> Optional[TypeInfo]:
        """推断元组字面量类型"""
        element_types = []
        for elt in expr.elements:
            element_types.append(self.infer_type(elt, context))

        return TypeInfo(TypeKind.TUPLE, "tuple", args=element_types)

    def _infer_set_type(
        self, expr: IRSet, context: InferenceContext
    ) -> Optional[TypeInfo]:
        """推断集合字面量类型"""

        # 推断所有元素的类型
        element_types = []
        for elt in expr.elements:
            element_types.append(self.infer_type(elt, context))

        if element_types:
            common_type = self._infer_common_type(element_types, context)
            return TypeInfo(TypeKind.GENERIC, "set", args=[common_type])

        # 空集合：尝试从期望类型推导
        if context.expected_type:
            # 如果期望类型是 set[T]，则使用 T 作为元素类型
            if context.expected_type.name == "set" and context.expected_type.args:
                return context.expected_type

        # 无法推导，返回 set（等价于 set[Any]）
        return TypeInfo(TypeKind.GENERIC, "set")

    def _infer_list_comprehension_type(
        self, expr: IRListComp, context: InferenceContext
    ) -> Optional[TypeInfo]:
        """推断列表推导式类型

        利用期望类型机制优化推导：
        如果存在期望类型 list[T]，则将 T 作为元素的期望类型传递给元素表达式
        """
        # 首先推断所有生成器，为目标变量设置类型
        for generator in expr.generators:
            self.infer_type(generator, context)

        # 确定元素的期望类型
        element_expected_type = None
        if context.expected_type:
            # 如果有期望类型，且是 list[T]，则元素期望类型是 T
            if (
                context.expected_type.kind == TypeKind.GENERIC
                and context.expected_type.name == "list"
                and context.expected_type.args
            ):
                element_expected_type = context.expected_type.args[0]

        # 使用元素期望类型推导元素表达式
        if element_expected_type:
            element_context = context.with_expected_type(element_expected_type)
            element_type = self.infer_type(expr.elt, element_context)
        else:
            element_type = self.infer_type(expr.elt, context)

        # 如果有期望类型，根据情况决定是否使用期望类型：
        # 1. 推导结果不明确（ANY/UNKNOWN）-> 使用期望类型（让期望类型提供精确信息）
        # 2. 期望类型是 ANY -> 使用 ANY（用户显式要求弱类型）
        if element_expected_type:
            if (
                element_type.kind == TypeKind.ANY
                or element_type.kind == TypeKind.UNKNOWN
            ):
                # 推导失败，使用期望类型
                element_type = element_expected_type
            elif element_expected_type.kind == TypeKind.ANY:
                # 用户显式要求弱类型，强制使用 ANY
                element_type = element_expected_type

        return TypeInfo(
            TypeKind.GENERIC,
            "list",
            args=[element_type],
        )

    def _infer_set_comprehension_type(
        self, expr: IRSetComp, context: InferenceContext
    ) -> Optional[TypeInfo]:
        """推断集合推导式类型

        利用期望类型机制优化推导：
        如果存在期望类型 set[T]，则将 T 作为元素的期望类型传递给元素表达式
        """
        # 首先推断所有生成器，为目标变量设置类型
        for generator in expr.generators:
            self.infer_type(generator, context)

        # 确定元素的期望类型
        element_expected_type = None
        if context.expected_type:
            # 如果有期望类型，且是 set[T]，则元素期望类型是 T
            if (
                context.expected_type.kind == TypeKind.GENERIC
                and context.expected_type.name == "set"
                and context.expected_type.args
            ):
                element_expected_type = context.expected_type.args[0]

        # 使用元素期望类型推导元素表达式
        if element_expected_type:
            element_context = context.with_expected_type(element_expected_type)
            element_type = self.infer_type(expr.elt, element_context)
        else:
            element_type = self.infer_type(expr.elt, context)

        # 如果有期望类型，根据情况决定是否使用期望类型
        if element_expected_type:
            if (
                element_type.kind == TypeKind.ANY
                or element_type.kind == TypeKind.UNKNOWN
            ):
                # 推导失败，使用期望类型
                element_type = element_expected_type
            elif element_expected_type.kind == TypeKind.ANY:
                # 用户显式要求弱类型，强制使用 ANY
                element_type = element_expected_type

        return TypeInfo(
            TypeKind.GENERIC,
            "set",
            args=[element_type],
        )

    def _infer_dict_comprehension_type(
        self, expr: IRDictComp, context: InferenceContext
    ) -> Optional[TypeInfo]:
        """推断字典推导式类型

        利用期望类型机制优化推导：
        如果存在期望类型 dict[K, V]，则将 K, V 作为键值的期望类型
        """
        # 首先推断所有生成器，为目标变量设置类型
        for generator in expr.generators:
            self.infer_type(generator, context)

        # 确定键和值的期望类型
        key_expected_type = None
        value_expected_type = None
        if context.expected_type:
            # 如果有期望类型，且是 dict[K, V]，则提取 K 和 V
            if (
                context.expected_type.kind == TypeKind.GENERIC
                and context.expected_type.name == "dict"
                and len(context.expected_type.args) >= 2
            ):
                key_expected_type = context.expected_type.args[0]
                value_expected_type = context.expected_type.args[1]

        # 使用期望类型推导键表达式
        if key_expected_type:
            key_context = context.with_expected_type(key_expected_type)
            key_type = self.infer_type(expr.key, key_context)
        else:
            key_type = self.infer_type(expr.key, context)

        # 使用期望类型推导值表达式
        if value_expected_type:
            value_context = context.with_expected_type(value_expected_type)
            value_type = self.infer_type(expr.value, value_context)
        else:
            value_type = self.infer_type(expr.value, context)

        # 如果有期望类型，根据情况决定是否使用期望类型
        if key_expected_type:
            if key_type.kind == TypeKind.ANY or key_type.kind == TypeKind.UNKNOWN:
                # 推导失败，使用期望类型
                key_type = key_expected_type
            elif key_expected_type.kind == TypeKind.ANY:
                # 用户显式要求弱类型，强制使用 ANY
                key_type = key_expected_type

        if value_expected_type:
            if value_type.kind == TypeKind.ANY or value_type.kind == TypeKind.UNKNOWN:
                # 推导失败，使用期望类型
                value_type = value_expected_type
            elif value_expected_type.kind == TypeKind.ANY:
                # 用户显式要求弱类型，强制使用 ANY
                value_type = value_expected_type

        return TypeInfo(
            TypeKind.GENERIC,
            "dict",
            args=[key_type, value_type],
        )

    def _infer_generator_comprehension_type(
        self, expr: IRGeneratorExp, context: InferenceContext
    ) -> Optional[TypeInfo]:
        """推断生成器表达式类型"""
        # 首先推断所有生成器，为目标变量设置类型
        for generator in expr.generators:
            self.infer_type(generator, context)

        # 推断元素表达式的类型
        element_type = self.infer_type(expr.elt, context)
        return TypeInfo(
            TypeKind.GENERIC,
            "generator",
            args=[element_type],
        )

    def _infer_comprehension_type(
        self, expr: IRComprehension, context: InferenceContext
    ) -> Optional[TypeInfo]:
        """推断推导式生成器类型"""
        # 推断迭代对象的类型
        iter_type = self.infer_type(expr.iter, context)

        # 如果迭代对象是泛型类型（如list[int]），提取元素类型
        if iter_type.kind == TypeKind.GENERIC and iter_type.args:
            element_type = iter_type.args[0]
        else:
            # 对于非泛型类型，尝试推断元素类型
            # 特殊处理：字符串迭代返回字符串
            if iter_type.name == "str":
                element_type = TypeInfo(TypeKind.PRIMITIVE, "str")
            else:
                # 其他情况返回 any，不硬编码类型名称
                element_type = TypeInfo.any()

        # 处理目标变量的类型推断
        self._infer_target_types(expr.target, element_type, context)

        return element_type

    def _infer_target_types(
        self, target: IRNode, element_type: TypeInfo, context: InferenceContext
    ) -> None:
        """推断推导式目标变量的类型

        Args:
            target: 目标变量节点（可能是单个变量或元组解包）
            element_type: 迭代器的元素类型
            context: 推断上下文
        """

        if isinstance(target, IRName):
            self._cache_type_info(target, element_type)
        elif isinstance(target, IRTuple):
            # 元组解包，需要根据元素类型的结构来分配类型
            if (
                element_type.kind == TypeKind.TUPLE
                or (
                    element_type.kind == TypeKind.GENERIC
                    and element_type.name == "tuple"
                )
            ) and element_type.args:
                # 如果元素类型是元组，按位置分配类型
                for i, element in enumerate(target.elements):
                    if i < len(element_type.args) and isinstance(element, IRName):
                        var_type = element_type.args[i]
                        self._cache_type_info(element, var_type)
            else:
                # 如果元素类型不是元组，所有变量都使用相同类型
                for element in target.elements:
                    if isinstance(element, IRName):
                        self._cache_type_info(element, element_type)

    def infer_assignment_type(
        self, assign_node: IRAssign, context: InferenceContext
    ) -> Optional[TypeInfo]:
        """推断赋值节点的类型"""

        # 处理类型注解，优先使用注解类型
        annotation_type = None
        if assign_node.annotation:
            annotation_type = parse_type(assign_node.annotation, assign_node)

        # 推断右侧表达式的类型
        # 如果有类型注解，将其作为期望类型传递给右侧表达式
        # 这样空列表/空字典等字面量可以根据注解推断出正确的类型
        value_type = None
        if assign_node.value:
            if annotation_type:
                # 使用注解类型作为期望类型
                context_with_hint = context.with_expected_type(annotation_type)
                value_type = self.infer_type(assign_node.value, context_with_hint)
            else:
                # 无注解：检查是否是重新赋值
                # 如果是重新赋值，使用目标变量的类型作为期望类型
                target = assign_node.get_target_expr()
                if target and isinstance(target, IRName):
                    # 尝试查找符号判断是否已声明
                    target_symbol = assign_node.lookup_symbol(target.id)
                    if target_symbol and target_symbol.type_info:
                        # 符号已存在：这是重新赋值，使用目标变量的类型作为期望类型
                        context_with_hint = context.with_expected_type(
                            target_symbol.type_info
                        )
                        value_type = self.infer_type(
                            assign_node.value, context_with_hint
                        )
                    else:
                        # 符号不存在：首次声明
                        value_type = self.infer_type(assign_node.value, context)
                else:
                    value_type = self.infer_type(assign_node.value, context)

        if not value_type:
            value_type = TypeInfo.any()

        resolved_type = resolve_type_annotation(
            annotation_type, value_type, assign_node
        )

        # 无注解的重新赋值：使用目标变量的已声明类型
        if not annotation_type:
            target = assign_node.get_target_expr()
            if target and isinstance(target, IRName):
                target_symbol = assign_node.lookup_symbol(target.id)
                if target_symbol and target_symbol.type_info:
                    # 符号已存在：这是重新赋值，使用目标变量的类型
                    resolved_type = target_symbol.type_info

        value_type = resolved_type if resolved_type else TypeInfo.any()

        # 检查是否是元组解包赋值
        if self._is_tuple_unpacking_assignment(assign_node):
            self._infer_tuple_unpacking_types(assign_node, value_type, context)
        elif self._is_multi_target_assignment(assign_node):
            self._infer_multi_target_types(assign_node, value_type, context)
        else:
            self._infer_single_target_type(assign_node, value_type, context)

        return value_type

    def _is_tuple_unpacking_assignment(self, assign_node: IRAssign) -> bool:
        """判断是否是元组解包赋值

        元组解包：x, y = (5, 10) 或 x, y = some_tuple
        """
        return assign_node.is_tuple_unpacking

    def _is_multi_target_assignment(self, assign_node: IRAssign) -> bool:
        """判断是否是多目标赋值

        多目标赋值：x = y = z = 10
        """
        target_exprs = assign_node.get_target_exprs()
        return len(target_exprs) > 1 and not assign_node.is_tuple_unpacking

    def _infer_single_target_type(
        self, assign_node: IRAssign, value_type: TypeInfo, context: InferenceContext
    ) -> None:
        """处理单目标赋值的类型推断"""
        target_expr = assign_node.get_target_expr()
        if target_expr and isinstance(target_expr, IRName):
            self._cache_type_info(target_expr, value_type)
            # 只在首次声明时更新符号的类型信息
            # 重新赋值不应该改变变量的类型（C++ 语义）
            is_declaration = assign_node.get_extension_param(
                "is_variable_declaration", True
            )
            if is_declaration:
                symbol = target_expr.lookup_symbol(target_expr.id)
                if symbol:
                    symbol.set_type_info(value_type)

    def _infer_multi_target_types(
        self, assign_node: IRAssign, value_type: TypeInfo, context: InferenceContext
    ) -> None:
        """处理多目标赋值的类型推断

        对于 x = y = z = 10，所有目标变量都应该有相同的类型
        """
        target_exprs = assign_node.get_target_exprs()
        target_declarations = assign_node.get_extension_param("target_declarations", {})

        for target_expr in target_exprs:
            if isinstance(target_expr, IRName):
                self._cache_type_info(target_expr, value_type)
                # 只在首次声明时更新符号的类型信息
                is_declaration = target_declarations.get(target_expr.id, True)
                if is_declaration:
                    symbol = target_expr.lookup_symbol(target_expr.id)
                    if symbol:
                        symbol.set_type_info(value_type)

    def _infer_tuple_unpacking_types(
        self, assign_node: IRAssign, value_type: TypeInfo, context: InferenceContext
    ) -> None:
        """处理元组解包赋值的类型推断

        对于 x, y = (5, 10)，需要从元组类型中提取每个元素的类型
        """
        target_exprs = assign_node.get_target_exprs()
        target_declarations = assign_node.get_extension_param("target_declarations", {})

        # 处理 tuple 类型：可能是 TUPLE 或 GENERIC (tuple 泛型类型)
        is_tuple_type = value_type.kind == TypeKind.TUPLE or (
            value_type.kind == TypeKind.GENERIC and value_type.name == "tuple"
        )
        if is_tuple_type and value_type.args:
            # 如果值类型是元组，按位置分配类型
            for i, target_expr in enumerate(target_exprs):
                if isinstance(target_expr, IRName) and i < len(value_type.args):
                    element_type = value_type.args[i]
                    self._cache_type_info(target_expr, element_type)
                    # 只在首次声明时更新符号的类型信息
                    is_declaration = target_declarations.get(target_expr.id, True)
                    if is_declaration:
                        symbol = target_expr.lookup_symbol(target_expr.id)
                        if symbol:
                            symbol.set_type_info(element_type)
        else:
            # 如果值类型不是元组，尝试从值表达式推断
            if isinstance(assign_node.value, IRTuple) and hasattr(
                assign_node.value, "elements"
            ):
                # 直接从元组字面量推断每个元素的类型
                elements = assign_node.value.elements
                for i, target_expr in enumerate(target_exprs):
                    if isinstance(target_expr, IRName) and i < len(elements):
                        element_type = self.infer_type(elements[i], context)
                        self._cache_type_info(target_expr, element_type)
                        # 只在首次声明时更新符号的类型信息
                        is_declaration = target_declarations.get(target_expr.id, True)
                        if is_declaration:
                            symbol = target_expr.lookup_symbol(target_expr.id)
                            if symbol:
                                symbol.set_type_info(element_type)
            else:
                # 尝试从可迭代对象推断元素类型
                element_type = self._infer_iterable_element_type(value_type)
                for target_expr in target_exprs:
                    if isinstance(target_expr, IRName):
                        self._cache_type_info(target_expr, element_type)
                        # 只在首次声明时更新符号的类型信息
                        is_declaration = target_declarations.get(target_expr.id, True)
                        if is_declaration:
                            symbol = target_expr.lookup_symbol(target_expr.id)
                            if symbol:
                                symbol.set_type_info(element_type)

    def _infer_iterable_element_type(self, iterable_type: TypeInfo) -> TypeInfo:
        """推断可迭代对象的元素类型"""
        if iterable_type.kind == TypeKind.GENERIC and iterable_type.args:
            return iterable_type.args[0]
        elif iterable_type.name == "str":
            return TypeInfo(TypeKind.PRIMITIVE, "str")  # 字符串迭代返回字符
        else:
            return TypeInfo.any()

    def _infer_common_type(
        self, types: List[TypeInfo], context: Optional[InferenceContext]
    ) -> TypeInfo:
        """推断类型列表的公共类型"""
        if not types:
            return TypeInfo.any()

        if len(types) == 1:
            return types[0]

        # 检查是否所有类型都相同
        first_type = types[0]
        if all(t.name == first_type.name and t.kind == first_type.kind for t in types):
            return first_type

        # 数值类型提升
        type_names = {t.name for t in types}
        if type_names.issubset({"int", "float"}):
            if "float" in type_names:
                return TypeInfo(TypeKind.PRIMITIVE, "float")
            else:
                return TypeInfo(TypeKind.PRIMITIVE, "int")

        # 如果无法找到公共类型，返回Any
        return TypeInfo.any()

    def _infer_generic_call_type(
        self, func_type: TypeInfo, arg_types: List[TypeInfo], context: InferenceContext
    ) -> Optional[TypeInfo]:
        """推断泛型函数调用类型"""
        # 使用 type_system 的泛型匹配功能
        # GenericTypeMatcher 已删除，使用 SymbolRegistry 替代
        if not arg_types:
            return None

        # 简化的泛型函数调用推断

        # 尝试匹配泛型函数类型
        if func_type.kind == TypeKind.GENERIC and func_type.args:
            # 简化处理：如果是泛型函数，返回其返回类型
            if func_type.return_type:
                return func_type.return_type

        return None

    def infer_function_type(
        self, func_node: "IRFunctionNode", context: InferenceContext
    ) -> Optional[TypeInfo]:
        """函数声明类型推断"""

        template_param_names = func_node.template_params
        if template_param_names:
            # 标记为模板函数（保留extension_param以兼容旧代码）
            func_node.set_extension_param("template_params", template_param_names)

            # 构建template_param_types（TypeVar名称 → TypeInfo映射）
            typevars = {}
            for tv_name in template_param_names:
                # 从模块查找TypeVar符号以获取完整TypeInfo
                tv_symbol = func_node.lookup_symbol(tv_name)
                if tv_symbol and tv_symbol.type_info:
                    typevars[tv_name] = tv_symbol.type_info
                else:
                    # 回退：创建基本的TYPE_PARAM
                    typevars[tv_name] = TypeInfo(kind=TypeKind.TYPE_PARAM, name=tv_name)

            func_node.set_extension_param("template_param_types", typevars)

        # 创建带有当前函数的上下文
        func_context = InferenceContext(
            mode=context.mode,
            error_messages=context.error_messages,
            current_class_type=context.current_class_type,
            infer_stack=context.infer_stack.copy(),
            compiler=context.compiler,
            expected_type=None,
            current_function=func_node,
        )

        # 推断返回类型
        return_type = self._infer_return_type_from_function(func_node, func_context)

        # 推断参数类型
        param_types = self._infer_parameter_types(func_node, func_context)

        # 嵌套函数闭包捕获分析（复用 Lambda 机制）
        if self._is_nested_function(func_node):
            captured_vars = self._analyze_function_captures(func_node)
            func_node.captured_vars = captured_vars  # 使用属性而不是 extension_param

            # 如果 captured_vars 为空，标记为简单函数（无捕获）
            if not captured_vars:
                func_node.set_extension_param("is_simple_non_capturing", True)

            # 收集捕获变量的类型信息
            captured_var_types = {}
            for var_name in captured_vars:
                var_type = self._get_captured_var_type(var_name, func_node)
                if var_type:
                    captured_var_types[var_name] = var_type

            func_node.set_extension_param("captured_var_types", captured_var_types)

        # 创建函数类型信息
        # 嵌套函数使用 "lambda" 作为类型名（复用 Lambda 的类型系统）
        type_name = (
            "lambda"
            if self._is_nested_function(func_node)
            else (func_node.name or "function")
        )

        func_type = TypeInfo(
            kind=TypeKind.FUNCTION,
            name=type_name,
            args=param_types,
            return_type=return_type,
        )

        return func_type

    def _infer_parameterized_constructor_call(
        self, expr: IRCall, arg_types: List[TypeInfo], context: InferenceContext
    ) -> Optional[TypeInfo]:
        """推导参数化类型构造调用

        例如：set[int]() -> TypeInfo(name="set", args=[TypeInfo(name="int")])

        Args:
            expr: 调用表达式（func 是 IRSubscript）
            arg_types: 参数类型列表
            context: 推导上下文

        Returns:
            推导出的返回类型
        """
        # expr.func 应该是 IRSubscript（如 set[int]）
        subscript = expr.func
        if not isinstance(subscript, IRSubscript):
            return None

        # 获取基础类型名称（如 set）
        if not isinstance(subscript.value, IRName):
            return None

        base_type_name = subscript.value.id

        # 查找类型符号
        type_symbol = expr.lookup_symbol(
            base_type_name, symbol_kinds=[SymbolKind.CLASS, SymbolKind.VARIABLE]
        )

        if not type_symbol or type_symbol.kind != SymbolKind.CLASS:
            return None

        # 使用已有的方法推导参数化类型
        return self._infer_parameterized_type_constructor(
            subscript, type_symbol, context
        )

    def _infer_parameterized_type_constructor(
        self, subscript_node: "IRSubscript", type_symbol, context: InferenceContext
    ) -> Optional[TypeInfo]:
        """推导参数化类型构造器的类型

        例如：set[int]() -> TypeInfo(name="set", args=[TypeInfo(name="int")])

        Args:
            subscript_node: 下标节点（如 set[int]）
            type_symbol: 类型符号
            context: 推导上下文

        Returns:
            推导出的具体类型，如果失败则返回 None
        """
        # 提取下标中的类型参数
        slice_node = subscript_node.slice

        # 推导类型参数
        type_args = []
        if isinstance(slice_node, IRTuple):
            # dict[str, int] 这种多参数形式
            for elem in slice_node.elements:
                arg_type = self._infer_type_from_type_annotation(elem, context)
                if arg_type:
                    type_args.append(arg_type)
        else:
            # set[int] 这种单参数形式
            arg_type = self._infer_type_from_type_annotation(slice_node, context)
            if arg_type:
                type_args.append(arg_type)

        if not type_args:
            return None

        # 构造参数化类型
        # 例如：set -> set[int]
        return TypeInfo(
            name=type_symbol.name,
            kind=TypeKind.GENERIC,
            args=type_args,
            module=type_symbol.type_info.module if type_symbol.type_info else None,
        )

    def _infer_type_from_type_annotation(
        self, node: IRNode, context: InferenceContext
    ) -> Optional[TypeInfo]:
        """从类型注解表达式推导类型

        例如：int -> TypeInfo(name="int")

        Args:
            node: 类型注解表达式节点（通常是 IRExpr，但接受 IRNode 以提高兼容性）
            context: 推导上下文

        Returns:
            推导出的类型信息
        """
        # IR 节点应该已经被类型推导处理过，直接获取其类型
        # 对于类型表达式（如 int, str），其类型信息就是其自身
        if isinstance(node, IRName):
            # 查找类型符号
            type_symbol = node.lookup_symbol(
                node.id, symbol_kinds=[SymbolKind.CLASS, SymbolKind.VARIABLE]
            )
            if type_symbol and hasattr(type_symbol, "type_info"):
                return type_symbol.type_info

        # 回退：尝试推导节点类型
        try:
            return self.infer_type(node, context)
        except Exception:
            return None

    def _is_compatible_generic_type(
        self, constructor_type: TypeInfo, expected_type: TypeInfo
    ) -> bool:
        """检查类型构造器和期望类型是否兼容

        例如：
        - set (构造器) 与 set[int] (期望) 兼容
        - list (构造器) 与 list[str] (期望) 兼容
        - set (构造器) 与 list[int] (期望) 不兼容

        Args:
            constructor_type: 类型构造器的类型信息
            expected_type: 期望的类型信息

        Returns:
            如果基础类型名称相同则返回 True，否则返回 False
        """
        if not constructor_type or not expected_type:
            return False

        # 检查基础类型名称是否匹配（忽略类型参数）
        return constructor_type.name == expected_type.name

    def _instantiate_generic_return_type(
        self, return_type: TypeInfo, expected_type: TypeInfo, call_node: IRCall
    ) -> Optional[TypeInfo]:
        """泛型函数实例化：根据期望类型推导类型参数

        例如：
        - 返回类型: set[T] (泛型)
        - 期望类型: set[int]
        - 推导结果: T = int
        - 实例化返回类型: set[int]

        Args:
            return_type: 函数的返回类型（可能包含泛型参数）
            expected_type: 上下文期望的类型
            call_node: 函数调用节点（用于存储类型参数绑定）

        Returns:
            实例化后的类型，如果不适用则返回 None
        """
        # 检查返回类型和期望类型的基础类型是否匹配
        if return_type.name != expected_type.name:
            return None

        # 检查返回类型是否包含泛型参数（通过检查 args 中是否有单字母类型参数）
        if not return_type.args:
            return None

        # 检查期望类型是否有具体的类型参数
        if not expected_type.args:
            return None

        # 推导类型参数映射
        type_param_bindings = {}

        # 简单情况：一对一映射（如 set[T] -> set[int]）
        if len(return_type.args) == len(expected_type.args):
            for ret_param, exp_param in zip(return_type.args, expected_type.args):
                # 如果返回类型参数是泛型参数（首字母大写，如 T, K, V, T_comparable）
                # 扩展识别：支持多字母的 TypeVar（如 T_comparable）
                if ret_param.name and ret_param.name[0].isupper():
                    type_param_bindings[ret_param.name] = exp_param

        # 如果没有推导出类型参数，返回 None
        if not type_param_bindings:
            return None

        # 将类型参数绑定存储到调用节点，供代码生成使用
        call_node.set_extension_param("generic_type_params", type_param_bindings)

        # 返回实例化后的类型（即期望类型）
        return expected_type

    def _parse_return_type(self, return_type_str: str) -> Optional[TypeInfo]:
        """解析返回类型字符串为 TypeInfo

        Args:
            return_type_str: 返回类型字符串，如 "list[K]"

        Returns:
            解析后的 TypeInfo，失败返回 None
        """
        return parse_type_with_context(return_type_str)

    def _has_template_params(self, type_info: TypeInfo, template_params: list) -> bool:
        """检查类型是否包含模板参数

        Args:
            type_info: 类型信息
            template_params: 模板参数名列表，如 ['K', 'T']

        Returns:
            如果包含模板参数返回 True
        """
        if not template_params:
            return False

        # 检查类型名是否是模板参数
        if type_info.name in template_params:
            return True

        # 递归检查类型参数
        if type_info.args:
            for arg in type_info.args:
                if self._has_template_params(arg, template_params):
                    return True

        return False

    def _has_template_params_in_type(self, type_info: TypeInfo) -> bool:
        """检查类型是否包含模板参数（通过符号系统判断）

        Args:
            type_info: 类型信息

        Returns:
            如果包含模板参数（TYPE_PARAM 或 TEMPLATE kind）返回 True
        """
        if not type_info:
            return False
        # 通过符号系统判断：TYPE_PARAM 或 TEMPLATE 都是模板参数
        if type_info.kind == TypeKind.TYPE_PARAM or type_info.kind == TypeKind.TEMPLATE:
            return True
        # 递归检查类型参数
        if type_info.args:
            for arg in type_info.args:
                if self._has_template_params_in_type(arg):
                    return True
        return False

    def _extract_template_params_from_args(
        self, signature, arg_types: List[TypeInfo], node: Optional["IRNode"] = None
    ) -> dict:
        """从函数参数类型中提取模板参数值

        Args:
            signature: 匹配的签名（包含参数类型定义）
            arg_types: 实际参数类型列表
            node: 上下文节点（用于符号查找）

        Returns:
            模板参数值映射，如 {"T_comparable": TypeInfo(name="int")}

        Example:
            签名: min(iterable: Iterable[T_comparable]) -> T_comparable
            参数: set[int]
            提取: {"T_comparable": TypeInfo(name="int")}
        """
        template_values = {}
        registry = get_global_registry()

        # 获取签名的模板参数列表（用于区分模板参数和普通可变参数）
        signature_template_params = set(signature.template_params or [])

        # 遍历每个参数，从签名参数类型和实际参数类型中提取模板参数
        for param_index, sig_param_type_str in enumerate(signature.param_types):
            # 处理可变参数（如 *T_comparable 或 *args）
            if sig_param_type_str.startswith("*"):
                # 提取参数名（去掉 *）
                param_name = sig_param_type_str[1:]

                # 判断是否是模板参数（而非普通可变参数）
                if param_name in signature_template_params:
                    # 这是可变模板参数（如 *T_comparable）
                    # 从所有实际参数中提取公共类型
                    if arg_types:
                        # 简化处理：使用第一个参数的类型作为模板参数值
                        # TODO: 更严格的实现应该检查所有参数类型是否兼容
                        template_values[param_name] = arg_types[0]
                # 否则是普通可变参数（如 *args），不提取模板参数
                continue

            if param_index >= len(arg_types):
                continue

            # 解析签名的参数类型（包含模板参数，如 Iterable[T_comparable]）
            sig_param_type = parse_type_with_context(
                sig_param_type_str, registry=registry
            )
            # 实际参数类型（具体类型，如 set[int]）
            actual_param_type = arg_types[param_index]

            # 模式匹配提取模板参数（传递 node 参数）
            self._match_and_extract_template_params(
                sig_param_type, actual_param_type, template_values, node
            )

        return template_values

    def _substitute_template_params(
        self, return_type: TypeInfo, template_values: dict
    ) -> Optional[TypeInfo]:
        """使用模板参数值替换返回类型中的模板参数

        Args:
            return_type: 返回类型（可能包含模板参数，如 T_comparable）
            template_values: 模板参数值映射，如 {"T_comparable": TypeInfo(int)}

        Returns:
            实例化后的返回类型，如果无法实例化则返回 None

        Example:
            return_type: T_comparable
            template_values: {"T_comparable": TypeInfo(int)}
            结果: TypeInfo(int)
        """
        # 如果返回类型本身就是模板参数，直接替换
        if return_type.name in template_values:
            return template_values[return_type.name]

        # 如果返回类型是泛型类型（如 Optional[T]），需要递归替换
        if return_type.args:
            instantiated_args = []
            for arg in return_type.args:
                instantiated_arg = self._substitute_template_params(
                    arg, template_values
                )
                if instantiated_arg:
                    instantiated_args.append(instantiated_arg)
                else:
                    instantiated_args.append(arg)

            # 创建新的 TypeInfo，使用实例化的参数
            if instantiated_args != return_type.args:
                new_type = copy(return_type)
                new_type.args = instantiated_args
                return new_type

        # 无法实例化，返回 None
        return None

    def _instantiate_constructor_return_type(
        self,
        return_type: TypeInfo,
        signature,
        arg_types: List[TypeInfo],
        node: Optional["IRNode"] = None,
    ) -> Optional[TypeInfo]:
        """实例化构造函数的返回类型

        根据 template_param_mapping 从参数类型中提取模板参数值。

        Args:
            return_type: 返回类型（可能包含模板参数如 list[K]）
            signature: 匹配的签名（包含 template_param_mapping）
            arg_types: 参数类型列表
            node: 上下文节点（用于符号查找）

        Returns:
            实例化后的返回类型，失败返回 None

        Example:
            签名: list(iterable: dict_keys[K]) -> list[K]
            参数: dict_keys[str]
            提取: K = str
            返回: list[str]
        """
        # 使用模式匹配从参数类型中提取模板参数值
        # 这种方法支持任意嵌套的模板参数
        template_values = {}

        # 获取全局注册表（用于类型解析）
        registry = get_global_registry()

        # 遍历每个参数，从签名参数类型和实际参数类型中提取模板参数
        for param_index, sig_param_type_str in enumerate(signature.param_types):
            if param_index >= len(arg_types):
                continue

            # 解析签名的参数类型（包含模板参数，如 list[tuple[K, V]]）
            # 必须传递 registry 以便正确识别模板参数（K, V 等）
            sig_param_type = parse_type_with_context(
                sig_param_type_str, registry=registry
            )
            # 实际参数类型（具体类型，如 list[tuple[str, int]]）
            actual_param_type = arg_types[param_index]

            # 模式匹配提取模板参数
            self._match_and_extract_template_params(
                sig_param_type, actual_param_type, template_values, node
            )

        # 如果无法从参数推断模板参数，使用默认类型填充
        if not template_values:
            # 检查返回类型是否包含未实例化的模板参数
            template_params_list = signature.template_params or []
            if self._has_template_params(return_type, template_params_list):
                # 尝试使用类型的默认类型填充
                # 例如：set[T] -> set[mc::variant]
                symbol = self._get_type_symbol_for_default_fill(return_type)
                if symbol and symbol.type_config:
                    default_type = symbol.type_config.get("default_type")
                    if default_type and return_type.args:
                        # 为所有模板参数使用默认类型

                        default_type_info = parse_type_with_context(default_type)
                        for arg in return_type.args:
                            if self._is_template_param(arg):
                                template_values[arg.name] = default_type_info

        if not template_values:
            return None

        # 替换返回类型中的模板参数
        return self._substitute_template_in_type(return_type, template_values)

    def _get_type_symbol_for_default_fill(self, type_info: TypeInfo):
        """获取类型符号用于填充默认类型

        Args:
            type_info: 类型信息（如 set[T]）

        Returns:
            对应的类型符号
        """
        registry = get_global_registry()
        return registry.lookup_type_symbol(type_info.name)

    def _is_template_param(self, type_info: TypeInfo) -> bool:
        """判断是否是未实例化的模板参数

        Args:
            type_info: 类型信息

        Returns:
            bool: 是否是模板参数
        """
        import re

        # 模板参数通常是单字母大写（T, K, V）或约束型（T_numeric）
        # 但为了安全，检查是否在已知的类型变量中
        if not type_info or not type_info.name:
            return False

        # 检查是否匹配模板参数的模式
        if not re.match(r"^[A-Z][A-Za-z0-9_]*$", type_info.name):
            return False

        # 排除具体类型
        CONCRETE_TYPES = {"Any", "None"}
        if type_info.name in CONCRETE_TYPES:
            return False

        # 如果是 PRIMITIVE 或 TEMPLATE 类型，且没有具体的 cpp_type，认为是模板参数
        if type_info.kind in (TypeKind.PRIMITIVE, TypeKind.TEMPLATE):
            return True

        return False

    def _match_and_extract_template_params(
        self,
        pattern_type: TypeInfo,
        actual_type: TypeInfo,
        template_values: dict,
        node: Optional["IRNode"] = None,
    ) -> None:
        """通过模式匹配从实际类型中提取模板参数值

        Args:
            pattern_type: 模式类型（包含模板参数，如 list[tuple[K, V]]）
            actual_type: 实际类型（具体类型，如 list[tuple[str, int]]）
            template_values: 模板参数值映射（输出）
            node: 上下文节点（用于符号查找）

        Example:
            pattern: list[tuple[K, V]]
            actual: list[tuple[str, int]]
            提取: K = str, V = int
        """
        if not pattern_type or not actual_type:
            return

        # 如果模式是模板参数（如 K, V），通过符号系统判断
        # TYPE_PARAM 表示从符号系统找到的类型参数（如 K, V, T）
        # TEMPLATE 表示签名中定义的模板参数
        if (
            pattern_type.kind == TypeKind.TYPE_PARAM
            or pattern_type.kind == TypeKind.TEMPLATE
        ):
            # 记录模板参数值
            template_values[pattern_type.name] = actual_type
            return

        # 如果基础类型名不匹配，检查是否是 Protocol 匹配
        if pattern_type.name != actual_type.name:
            # 检查是否是 Protocol 类型（如 Iterable, Comparable）
            # 如果是 Protocol，检查实际类型是否实现了该 Protocol
            if is_protocol_implementation(pattern_type, actual_type):
                # Protocol 匹配：提取类型参数
                # 通用策略：只提取模板参数，跳过具体类型
                # 例如：Coroutine[Any, Any, T]中，Any是具体类型（跳过），T是模板参数（提取）

                if pattern_type.args and actual_type.args:
                    # 收集所有模板参数（kind为TEMPLATE或TYPE_PARAM）
                    template_param_indices = []
                    for i, pattern_arg in enumerate(pattern_type.args):
                        if pattern_arg.kind in [TypeKind.TEMPLATE, TypeKind.TYPE_PARAM]:
                            template_param_indices.append(i)

                    # 根据protocol的语义映射到actual的参数
                    # 对于Coroutine[Any, Any, T]：只有第3个参数是模板，映射到result[int]的第1个参数
                    if pattern_type.name == "Coroutine" and template_param_indices:
                        # Coroutine协议：第3个参数（返回值类型）映射到actual的第1个参数
                        if 2 in template_param_indices and len(actual_type.args) >= 1:
                            pattern_return_type = pattern_type.args[2]  # T
                            actual_return_type = actual_type.args[0]  # int
                            self._match_and_extract_template_params(
                                pattern_return_type,
                                actual_return_type,
                                template_values,
                                node,
                            )
                    elif (
                        pattern_type.name in ["Iterable", "Iterator"]
                        and template_param_indices
                    ):
                        # Iterable/Iterator协议：从类型的 iterator_element_type 配置推导元素类型
                        # 例如：Iterable[T] 匹配 dict_items[K, V]
                        # 从 dict_items 的配置读取 iterator_element_type = "tuple[K, V]"
                        element_type = self._infer_protocol_type_param(
                            pattern_type.name, actual_type, node
                        )
                        if element_type and 0 in template_param_indices:
                            # Iterable[T] 或 Iterator[T] 的 T
                            pattern_element_type = pattern_type.args[0]
                            self._match_and_extract_template_params(
                                pattern_element_type,
                                element_type,
                                template_values,
                                node,
                            )
                    else:
                        # 其他Protocol：按位置一对一映射（跳过非模板参数）
                        actual_idx = 0
                        for pattern_idx in template_param_indices:
                            if actual_idx < len(actual_type.args):
                                self._match_and_extract_template_params(
                                    pattern_type.args[pattern_idx],
                                    actual_type.args[actual_idx],
                                    template_values,
                                    node,
                                )
                                actual_idx += 1
                return
            else:
                # 类型不匹配
                return

        # 递归匹配类型参数
        if pattern_type.args and actual_type.args:
            for pattern_arg, actual_arg in zip(pattern_type.args, actual_type.args):
                self._match_and_extract_template_params(
                    pattern_arg, actual_arg, template_values, node
                )

    def _infer_protocol_type_param(
        self, protocol_name: str, actual_type: TypeInfo, node: Optional["IRNode"] = None
    ) -> Optional[TypeInfo]:
        """从实际类型推断 Protocol 的类型参数

        通过类型定义中的 iterator_element_type 字段来确定迭代器元素类型。
        例如：Iterable[T] 匹配 dict_items[K, V]，从配置中读取
        iterator_element_type = "tuple[K, V]"，推断出 T = tuple[K, V]。

        Args:
            protocol_name: Protocol 名称（如 "Iterable", "Iterator"）
            actual_type: 实际类型（如 dict_items[int, int]）
            node: 上下文节点（用于符号查找，支持 stub 和用户自定义类型）

        Returns:
            Protocol 的类型参数值，如果无法推断则返回 None
        """
        # 只处理迭代器相关的 Protocol
        if protocol_name not in ["Iterable", "Iterator"]:
            return None

        # 查找类型符号（优先从 node.lookup_symbol，支持 stub 和作用域）
        type_symbol = None
        if node:
            # 先尝试通过 node 查找（支持 stub 导入和用户自定义类型）
            type_symbol = node.lookup_symbol(actual_type.name)

        # 如果没有找到符号或符号没有 type_config 或 iterator_element_type，
        # 回退到全局符号表（对于 builtin 类型）
        # 这对于泛型类型（如 list[int]）特别重要，因为 node.lookup_symbol 可能只找到非泛型版本
        if (
            not type_symbol
            or not type_symbol.type_config
            or not type_symbol.type_config.get("iterator_element_type")
        ):
            from mcpy.symbol_registry import get_global_registry

            registry = get_global_registry()
            type_symbol = registry.lookup_type_symbol(
                actual_type.name, actual_type.args
            )

        if not type_symbol or not type_symbol.type_config:
            return None

        # 从类型配置中读取 iterator_element_type
        element_type_str = type_symbol.type_config.get("iterator_element_type")
        if not element_type_str:
            return None

        # 解析元素类型
        from mcpy.type_system import parse_type_with_context

        element_type = parse_type_with_context(element_type_str, node=node)
        if not element_type:
            return None

        # 替换泛型参数（如 K, V）为实际类型
        return self._substitute_generic_params(element_type, actual_type)

    def _substitute_template_in_type(
        self, type_info: TypeInfo, template_values: dict
    ) -> TypeInfo:
        """替换 TypeInfo 中的模板参数

        Args:
            type_info: 原始类型信息
            template_values: 模板参数值映射，如 {'K': TypeInfo(name='str')}

        Returns:
            替换后的类型信息
        """
        # 如果类型名是模板参数，直接替换
        if type_info.name in template_values:
            return template_values[type_info.name]

        # 如果有类型参数，递归替换
        if type_info.args:
            new_args = []
            for arg in type_info.args:
                new_arg = self._substitute_template_in_type(arg, template_values)
                new_args.append(new_arg)

            # 创建新的 TypeInfo
            return TypeInfo(
                kind=type_info.kind,
                name=type_info.name,
                args=new_args,
            )

        return type_info

    def _check_type_compatibility(
        self, expected: TypeInfo, actual: TypeInfo, param_name: str, call_node: IRCall
    ) -> None:
        """检查类型兼容性，如果不兼容则报告编译错误

        Args:
            expected: 期望的类型
            actual: 实际的类型
            param_name: 参数名称（用于错误信息）
            call_node: 调用节点（用于错误位置和符号查找）

        Raises:
            编译错误（通过 codegen.errors 模块）
        """
        # 跳过无法推导的类型
        if not actual or actual.kind == TypeKind.UNKNOWN or actual.name == "Unknown":
            return  # 无法验证，跳过检查

        # 跳过模板类型参数（无法在此阶段验证）
        # TypeKind.TYPE_PARAM - 函数签名中的类型参数（如 Callable[[T], R] 中的 T、R）
        # TypeKind.TEMPLATE - 模板参数（如 list[T] 中的 T）
        if expected.kind == TypeKind.TYPE_PARAM or actual.kind == TypeKind.TYPE_PARAM:
            return
        if expected.kind == TypeKind.TEMPLATE or actual.kind == TypeKind.TEMPLATE:
            return

        # 跳过 tuple 类型检查（tuple 涉及复杂的迭代器类型推导，需要单独处理）
        # 这是一个已知问题：for item in dict.items() 中 item 的类型推导不准确
        if expected.name == "tuple" or actual.name == "tuple":
            return

        # 特殊处理：Callable 协议
        if expected.name == "Callable":
            if not is_callable_compatible(expected, actual):

                # 构造清晰的错误信息
                expected_param_count = len(expected.args) if expected.args else 0
                actual_param_count = len(actual.args) if actual.args else 0

                error_msg = (
                    f"参数 '{param_name}' 类型不匹配:\n"
                    f"  期望: Callable 需要 {expected_param_count} 个参数\n"
                    f"  实际: {actual.name} 有 {actual_param_count} 个参数"
                )

                raise CodeGenError(error_msg, call_node)

        # 其他类型使用通用兼容性检查（传递 call_node 用于符号查找）
        if not types_compatible(expected, actual, call_node):
            error_msg = (
                f"参数 '{param_name}' 类型不匹配:\n"
                f"  期望: {expected.name}\n"
                f"  实际: {actual.name}"
            )

            raise CodeGenError(error_msg, call_node)

    # ===== 类型守卫分析方法 =====

    def _analyze_type_guard(
        self, condition: IRNode, context: InferenceContext
    ) -> dict[str, TypeNarrowingInfo]:
        """分析条件表达式中的类型守卫模式

        Args:
            condition: 条件表达式节点
            context: 推断上下文

        Returns:
            变量名到类型收窄信息的映射
        """
        narrowing_infos = {}

        # 模式 1: if optional_var:  检查 Optional 类型
        if isinstance(condition, IRName):
            var_type = self.infer_type(condition, context)
            if self._wrapper_registry.is_wrapper_type(var_type):
                inner_type = self._wrapper_registry.get_inner_type(var_type)
                if inner_type:
                    narrowing_infos[condition.id] = TypeNarrowingInfo(
                        var_name=condition.id,
                        original_type=var_type,
                        narrowed_type=inner_type,
                        narrowing_kind="optional_check",
                    )

        # 模式 2: if not optional_var:  否定检查（用于负向守卫）
        elif isinstance(condition, IRUnaryOp):
            narrowing_info = self._analyze_not_check(condition, context)
            if narrowing_info:
                narrowing_infos[narrowing_info.var_name] = narrowing_info

        # 模式 3: if var is not None:
        elif isinstance(condition, IRCompare):
            narrowing_info = self._analyze_is_not_none_check(condition, context)
            if narrowing_info:
                narrowing_infos[narrowing_info.var_name] = narrowing_info

        # 模式 4: if isinstance(var, Type):
        elif isinstance(condition, IRCall):
            narrowing_info = self._analyze_isinstance_check(condition, context)
            if narrowing_info:
                narrowing_infos[narrowing_info.var_name] = narrowing_info

        return narrowing_infos

    def _analyze_not_check(
        self, unary_node: IRUnaryOp, context: InferenceContext
    ) -> Optional[TypeNarrowingInfo]:
        """分析 `not optional_var` 模式（用于负向守卫）

        这个模式在 then_body 中不收窄（因为是否定），
        但如果 then_body 终止（break/return），则在 if 之后收窄。

        Args:
            unary_node: 一元操作节点
            context: 推断上下文

        Returns:
            类型收窄信息（标记为否定模式）
        """
        # 检查是否是 not 操作
        if unary_node.op not in ["Not", "not"]:
            return None

        operand = unary_node.operand
        if not isinstance(operand, IRName):
            return None

        var_type = self.infer_type(operand, context)

        # 只处理 Optional 类型
        if not self._wrapper_registry.is_wrapper_type(var_type):
            return None

        inner_type = self._wrapper_registry.get_inner_type(var_type)
        if not inner_type:
            return None

        # 返回收窄信息，但标记为 "negated"
        # 这个信息在 _infer_if_with_type_narrowing 中会被特殊处理
        return TypeNarrowingInfo(
            var_name=operand.id,
            original_type=var_type,
            narrowed_type=inner_type,
            narrowing_kind="negated_optional_check",  # 标记为否定检查
        )

    def _analyze_is_not_none_check(
        self, compare_node: IRCompare, context: InferenceContext
    ) -> Optional[TypeNarrowingInfo]:
        """分析 `var is not None` 模式

        Args:
            compare_node: 比较节点
            context: 推断上下文

        Returns:
            类型收窄信息，如果不是该模式则返回 None
        """
        if not (
            len(compare_node.ops) == 1 and compare_node.ops[0] in ["is not", "IsNot"]
        ):
            return None

        left = compare_node.left
        right = compare_node.comparators[0] if compare_node.comparators else None

        # 检查右侧是否是 None
        if not (isinstance(right, IRConstant) and right.value is None):
            return None

        # 检查左侧是否是变量名
        if not isinstance(left, IRName):
            return None

        var_type = self.infer_type(left, context)

        # 只处理 Optional 类型
        if not self._wrapper_registry.is_wrapper_type(var_type):
            return None

        inner_type = self._wrapper_registry.get_inner_type(var_type)
        if not inner_type:
            return None

        return TypeNarrowingInfo(
            var_name=left.id,
            original_type=var_type,
            narrowed_type=inner_type,
            narrowing_kind="is_not_none",
        )

    def _analyze_isinstance_check(
        self, call_node: IRCall, context: InferenceContext
    ) -> Optional[TypeNarrowingInfo]:
        """分析 `isinstance(var, Type)` 模式

        Args:
            call_node: 调用节点
            context: 推断上下文

        Returns:
            类型收窄信息，如果不是该模式则返回 None
        """
        # 检查是否是 isinstance 调用
        if not (
            isinstance(call_node.func, IRName) and call_node.func.id == "isinstance"
        ):
            return None

        if len(call_node.args) != 2:
            return None

        var_node = call_node.args[0]
        type_node = call_node.args[1]

        # 检查第一个参数是否是变量名
        if not isinstance(var_node, IRName):
            return None

        # 获取目标类型
        if isinstance(type_node, IRName):
            target_type = parse_type_with_context(type_node.id, call_node)
        else:
            return None

        var_type = self.infer_type(var_node, context)

        return TypeNarrowingInfo(
            var_name=var_node.id,
            original_type=var_type,
            narrowed_type=target_type,
            narrowing_kind="isinstance",
        )


global_engine = TypeInferenceEngine()


def infer_type(node: IRNode, context: Optional[InferenceContext] = None) -> TypeInfo:
    """推导IR节点的类型"""
    if not context:
        context = InferenceContext()
    return global_engine.infer_type(node, context)
